macxred / cashctrl_ledger

Implementation of the abstract pyledger.LegderEngine interface with CashCtrl accounting service.
MIT License
0 stars 0 forks source link

Implement FX_revaluation() method #73

Open AlexTheWizardL opened 2 months ago

AlexTheWizardL commented 2 months ago

Current state:

We already created working FX_revaluation() method that covers our needs in the #72.

Tasks:

lasuk commented 1 month ago

Clarifications

  1. In accounting systems using price units different from the reporting currency, such as foreign currencies, the value of goods our cash defined in a non-reporting currency must be periodically adjusted, as the prices or exchange rates flucutate.
  2. Both pyledger and cashctrl ledger do have a data type and a functionality to deal with such revaluations. The two definitions overlap but are not identical.
  3. We first want to refine the pledger deviation of revaluations (add and optional price, review column names) and then need to map this definition not CashCtrl.

Example pyledger revaluation data:

date, adjust, credit, debit, price, text
2023-01-31,             1400:1499, 3270, 3270,      , FX adjustment Portfolio
2023-02-28,             1400:1499, 3270, 3270,      , FX adjustment Portfolio
2023-01-31, 0000:1999 - 1400:1499, 6949, 6949,      , FX adjustment
2023-02-28, 0000:1999 - 1400:1499, 6949, 6949,      , FX adjustment

Python code to translate our format into cashstrl's:

def fx_revaluation(self, cash_ctrl: LedgerEngine) -> pd.DataFrame:

    adjustment = self.fx_adjustments()
    base_currency = self.base_currency
    for row in adjustment.to_dict('records'):
        date = row['date']
        accounts = self.account_range(row['adjust'])
        accounts = set(accounts['add']) - set(accounts['subtract'])
        accounts = list(accounts)
        df = pd.DataFrame({
            "foreign_currency_account": accounts,
            "currency": [self.account_currency(account) for account in accounts],
            "fx_gain_loss_account": row['credit'] # TODO: if amount > 0 else row['debit']
        })
        df = df.loc[df['currency'] != base_currency, :]
        fx_rate = {}
        for currency in df['currency'].unique():
            price = self.price(currency, date=date, currency=base_currency)
            assert price[0] == base_currency
            fx_rate[currency] = price[1]
        df['exchange_rate'] = [fx_rate[currency] for currency in df['currency']]
        cash_ctrl.FX_revaluation(df, date=date)

Example cashctrl revaluation data:

date, foreign_currency_account, currency, fx_gain_loss_account, exchange_rate
2023-01-31,               1400,      CHF,                 3270,          1.00
2023-01-31,               1401,      EUR,                 3270,          0.93

Actions needed:

  1. Extend our fx_adjustment format with a price column.
    • Maybe find better names instead of adjust, credit, debit
  2. Implement accessors, mutators and mirroring in pyledger
  3. Implement accessors, mutators and mirroring in cashctrl_ledger
    • Raise an error or warning if credit and debit accounts differ (CashCtrl allows us to solely specify a singl account)
    • Fill missing prices as shown in above example (I believe cashCtrl requires prices to be set; its worth checking my assumption before implement anyting).
    • Look up currency from the foreign_currency_account as shown in above example
    • Ignore text (cashctrl has a hard-coded text)