Correctly account for unrealised gains across multiple years

This commit is contained in:
RunasSudo 2020-06-07 22:43:11 +10:00
parent 25f0e8eeba
commit c144124fc1
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
3 changed files with 20 additions and 10 deletions

View File

@ -56,6 +56,8 @@ Ledger-pyreport by default observes the convention that positive amounts in Ledg
A commodity which has *any* price data in Ledger (including those specified through `@` or `@@`, or explicitly through `P`) will be regarded as a commodity measured at fair market value, and automatically revalued accordingly. A commodity which has *no* price data in Ledger (i.e. lot prices through `{…}` or `{{…}}` only) will be regarded as a commodity measured at historical cost, and will not be subsequently revalued.
In accordance with accrual accounting, unrealised gains are charged to the Unrealized Gains income/expense account shown in *config.yml* in the period in which they occur. Subsequent realisations of those gains should be charged against the Unrealized Gains account within the Ledger journal. Alternatively, if charged to a different account (e.g. a realised Capital Gains income account), note that the Unrealized Gains account will contain a *contra* balance corresponding to previous years gains which are now realised.
## Comparative statements
ledger-pyreport can be used to produce comparative statements, for example ‘compare *n* years’ or ‘compare *n* months’.

View File

@ -47,19 +47,22 @@ def trial_balance(ledger, date, pstart, commodity, label=None):
for account in set(list(r_date.keys()) + list(r_pstart.keys())):
if account in r_pstart:
# Charge previous unrealized gains to Accumulated OCI
#r_pstart[account].postings[1].account = ledger.get_account(config['accumulated_oci'])
accumulated = r_pstart[account].postings[0].amount
tb_date.balances[account.name] = tb_date.get_balance(account) + r_pstart[account].postings[0].amount
if r_pstart[account].postings[1].account.is_income or r_pstart[account].postings[1].account.is_expense:
tb_date.balances[config['retained_earnings']] = tb_date.get_balance(ledger.get_account(config['retained_earnings'])) - r_pstart[account].postings[0].amount
elif r_pstart[account].postings[1].account.is_oci:
tb_date.balances[config['accumulated_oci']] = tb_date.get_balance(ledger.get_account(config['accumulated_oci'])) - r_pstart[account].postings[0].amount
else:
tb_date.balances[config['unrealized_gains']] = tb_date.get_balance(ledger.get_account(config['accumulated_oci'])) - r_pstart[account].postings[0].amount
tb_date.balances[account.name] = tb_date.get_balance(account) + accumulated
tb_date.balances[config['accumulated_oci']] = tb_date.get_balance(ledger.get_account(config['accumulated_oci'])) - accumulated
# Reversing entry
trn_reversal = r_pstart[account].reverse(None, pstart, '<Reversal of Unrealized Gains>')
ledger.transactions.insert(0, trn_reversal)
tb_date.balances[account.name] = tb_date.get_balance(account) + trn_reversal.postings[0].amount
tb_date.balances[config['unrealized_gains']] = tb_date.get_balance(ledger.get_account(config['unrealized_gains'])) - trn_reversal.postings[0].amount
if account in r_date:
if account in r_pstart:
# Adjust for this year's unrealized gains only
r_date[account].postings[0].amount -= accumulated
r_date[account].postings[1].amount += accumulated
tb_date.balances[account.name] = tb_date.get_balance(account) + r_date[account].postings[0].amount
tb_date.balances[config['unrealized_gains']] = tb_date.get_balance(ledger.get_account(config['unrealized_gains'])) - r_date[account].postings[0].amount

View File

@ -84,6 +84,11 @@ class Transaction:
result.append(' {} {}'.format(posting.account.name, posting.amount.tostr(False)))
return '\n'.join(result)
def reverse(self, id, date, description, code=None, uuid=None):
result = Transaction(self.ledger, id, date, description, code, uuid)
result.postings = [Posting(p.transaction, p.account, -p.amount, p.comment, p.state) for p in self.postings]
return result
@property
def has_comment_detail(self):
return any(p.comment for p in self.postings)