hledger icon indicating copy to clipboard operation
hledger copied to clipboard

stricter/more correct handling of unbalanced multicommodity transactions

Open psb777 opened this issue 5 years ago • 44 comments

It is suggested in the docs at https://hledger.org/1.14/journal.html under the "Transaction Prices" section that one can record an FX transaction thusly in the journal:

2009/1/1
  assets:euros     €100          ; one hundred euros purchased
  assets:dollars  $-135          ; for $135

and this works. But it ought not to. The balance sheet no longer balances because neither commodity posting has a contra. hledger should never allow this as the basic double entry check that one's accounts are in order is that the balance sheet sums to zero in all currencies (and securities and commodities.) Anyone doing FX in this way loses this most basic of accountancy checks, that every transaction balances in every currency.

The correct way to post the above is something like the following:

2009/1/1
  assets:euros     €100          ; one hundred euros purchased
  assets:dollars  $-135          ; for $135
  control:fx

Then the balancing postings automatically get done for you by hledger, and the balance sheet continues to balance.

If one believes that the invention of double entry bookkeeping was a great thing then hledger should prevent an imbalance being created in the balance sheet for FX transations just as it does for all other transactions.

Possibly helpful details:

  • a minimal reproducible example: see above
  • related documentation: referenced above
  • my hledger version: 1.14
  • installation: apt-get
  • platform: devuan (i.e. vanilla debian but without systemd)

psb777 avatar Jan 16 '20 15:01 psb777

Thanks for the report and clear advice. We also have #758 open for this. I would be fine with this personally, but it would be a breaking change in very long-established behaviour so I think a clear consensus and favourable community discussion of this are required.

simonmichael avatar Jan 16 '20 15:01 simonmichael

I now see this has been reported long ago. It is the same issue as #115 and #86. I very much like the solution proposed in #115 and would like to re-emphasise that the basic rules of double entry book-keeping should be enforced by any good accounting system. The alternative of memorandum style (single entry) book-keeping is available to "accountants" but note that it is not allowed by hledger on transactions with postings only in one currency. Every transaction must balance in every commodity, and if this rule is not followed then the balance sheet will not sum to zero, the most standard basic check that one's books are in order. Repeating myself, I know.

One doesn't allow a transaction with only one posting for the purchase of a pencil. One has to find a place for the contra, there are two entries, one in expenses and another in the cashbook. There is no difference, purchase of a pencil, and purchase of FX. If one wants to account for pens as a commodity then that too can be done, but there are 4 postings. You post to stationarycupboard and assets in the "pencil" commodity, and you post to cashbook and expenses for the currency. Same with FX: You need to find somewhere to post the contras, most obviously the contras are posted to the reserves or equity account (because one is actually changing the reserves when one does FX), or some FX control account.

To muddy the waters as does the hledger docs by considering what one is using the FX for is not a good idea. In real life one does the FX transaction and the foreign purchase in two separate independent transactions, one at the bank and the other with the seller. The same should be true in your book-keeping. You can choose either to keep the books completely ignorant of the FX currency and post everything in local currency equivalents, or you can choose to post the FX to the books. If you post the FX to the books then the FX currency postings must balance. What hledger and Ledger before it seem to have supported is the halfway house which allows memorandum accounting, not double entry, for FX. And the breaking of double entry rules which protect the integrity of your accounts.

psb777 avatar Jan 17 '20 01:01 psb777

@psb777 , may I disagree with your suggestion. I consider they way hledger works now in fact balance and respect the double entry principle.

It is better said that in your example, the transaction doesn't explicit balance, but if you consider it is implicit that one EUR equal 1.35 USD, it does indeed balance, at least in the default currency.

I guess you may be tracking only currency transactions. Because people usually works with 2 or 3, balancing like you are suggesting makes sense. But if you are tracking investments, you will end up with a bunch of commodities, and your balance report will be unreadable if you want to see all commodities balancing in one shot.

This is how I think your example should be written:

D USD 1,000.00

P 2009-01-01 EUR USD 1.350
2009/1/1
  assets:euros                 EUR 100 @@ 135 USD          ; one hundred euros purchased
  assets:dollars               USD -135                                 ; for $135

Balance in USD

hledger b -B
                   0  assets
        USD -135.000    dollars
         USD 135.000    euros
--------------------
                   0

balance in EUR

hledger b -X EUR
                   0  assets
            EUR -100    dollars
             EUR 100    euros
--------------------
                   0

This way your transaction is balancing in each currency. In your suggestion, you create an account that is not Asset, Liability, Income not Expense. It will be difficult to explain that to a new user

edkedk99 avatar Jan 30 '20 14:01 edkedk99

I follow what you say but you are not correct. What you describe is a mix'n'match of memorandum (single entry) bookkeeping with double entry. So fundamental is the following in double entry:

(We assume signed amounts in all the following where CR is -ve and DR is +ve. This can all be restated in CR and DR with positive only numbers if reqd.)

(1) Assets + Reserves + Liabilities = 0, and this is true for each commodity in which one posts.

(2) Each transaction preserves (1) above and this requires that the amounts in each commodity sum to zero in each transaction.

When one opens one's accounts for an existing business one would make many postings and for the GBP current account one posts that to an ASSET:CASH account - representing what is yours at the bank, and one posts a contra to the RESERVES:CASH account representing what belongs to the shareholders of the business, should the business pay out its assets, or should the business close. If the business has a USD account then should the business close then what the business will own to the shareholders will be the USD in that account. Therefore there must be a balancing USD entry in RESERVES:CASH if there is ASSETS:CASH entry in USD.

The fundamental rules of accounting say if you have an ASSET then it must appear in the RESERVES (and if you have a LIABILITY it too must appear in the RESERVES). If you insist on having a USD balance anywhere in ASSETS (or LIABILITIES) then there MUST be a corresponding USD balance in RESERVES.

That's why this is INCORRECT:

2020/02/02: Convert some of our GBP to USD
    assets:cash:Barclays       -100 GBP
    assets:cash:Citibank         130 USD

but this is CORRECT

2020/02/02: Convert some of our GBP to USD
    assets:cash:Barclays       -100 GBP
    reserves:cash                    100 GBP
    assets:cash:Citibank         130 USD
    reserves:cash                    -130 USD

There is one other correct way, and that is to post everything in your reporting currency GBP (say) and have no USD postings at all. That will require FX P&L postings from time to time but it works.

What does not work is the half way house nonsense of a USD posting in ASSETS (or LIABILITIES) not balanced by a RESERVES USD posting. What that would do is create a set of accounts which breaks the A+L=R equation which has two consequences. The first is a technical but important that an imbalance doesn't immediate inform one of a problem with the accounts; the second is that it MISREPRESENTS the position to the shareholders.

psb777 avatar Feb 03 '20 03:02 psb777

@edkedk99 : Your misunderstanding seems to arise or you justify from the balancing postings going to "fx:control". Of course that account is an EQUITY (or RESERVES) account as it is neither in ASSETS nor in LIABILITIES. The account could be better named. It could be EQUITY:CONTROL:FX accumulated to period end when the balances are posted to EQUITY:CASH or they could be posted to EQUITY:CASH immediately.

As explained above, when you set up a new accounting system for an existing business you debit the cash at bank to ASSETS:CASH (or a sub-account of that) as that is owed to the business by the bank and you credit the contra to the RESERVES:CASH account because that is what the business owes the shareholders. When you switch your ASSETS from one currency to another the same MUST happen in the RESERVES.

psb777 avatar Feb 03 '20 03:02 psb777

@psb777,

The naming convention in your post confused me, but know it is clear that 'control:fx' or 'reserves:cash' means 'Equity:Capital'

I will insist in my point, even considering you are correct in the "double entry principles". The problem I see on how you are doing your accounting is on having a **multi-currency EQUITY account". I am not an accountant, so please correct me if I am wrong, but the convention is that EQUITY, and more broadly a BALANCE SHEET is always in one single currency. I have never seen, even in public companies listed in exchanges to post its balance sheets like you propose. AFAIK regular accounting software doesn't allow that to happen.

I think Hledger was not designed with focus 100% to be this multi-currency/commodity tool you expect, but rather to allow you to do single-currency accounting with some helpers that allows you to follow the price evolution of your assets, and that is not part of a strict accounting software. In my view, you use hledger to do strict accounting or to follow your asset evolution. Expecting hledger to be both at the same time will cause many problems or will get too complicated.

But anyway, this is just different opinions, one more strict than the other. Some days before seeing your post, I realized 'hledger-iadd' followed you understanding in this topic. I filled an issue at 'hledger-iadd' repository, defending that because if 'hledger' allows this entry, 'hledger-iadd' should allow too. They accepted my reasoning and adjusted their software.

I suggest you to check the addon 'hledger-check.hs'. It will allow you to do the check you think it is missing. I think there is a low probability that hledger developers make the change you propose because it could break the journal for existing users

edkedk99 avatar Feb 03 '20 18:02 edkedk99

it could break the journal for existing users

We could help with migration, or it could be an option, eg part of --strict mode.

simonmichael avatar Feb 03 '20 18:02 simonmichael

@simonmichael ,

If that is feasible, it is a solution. I personally struggle with the concept of having a multi-currency balance sheet, because this is not an accounting standard, but on the other side, I am new to hledger.

I also worry how this new way of balance check will add in complexities for a new user who drops in hledger.org and tries to understand the commodity concept, which even today is not that easy.

edkedk99 avatar Feb 03 '20 21:02 edkedk99

In my view, if hledger maintains an historic compatibility with the also incorrect Ledger then it is that compatibility mode which requires a command line flag, not the proper implementation of double entry which hledger does so effortlessly, but not being documented, is not done the easy way by many.

I am not trying to create work but save everyone work. It really is easier and more readily understood the proper way. Please read on but first let me address some issues raised.

Equity, Reserves and Capital are equivalent words from a double entry accounting perspective and mean effectively the same thing for different styles of business. I see that hledger docs see Equity and Reserves as equivalent.

Multi-currency and multi-commodity and multi-security double entry bookkeeping is done routinely in financial firms where they must properly account for assets, liabilities and reserves which have long since been dematerialised (to use a jargon word) and turned into debt and options and futures and derivatives just as cash was long ago. It is far from unusual, indeed mandatory in any City firm.

However, regulatory reporting and tax reporting often requires that everything be reported in one designated base reporting currency. In such circumstance there can be ZERO balances denominated anywhere in the accounts except in the specified currency. That's where the hledger -V and -X xxx options come in very useful. However, there are also ZERO circumstances where the sum of the ASSETS, LIABILITES and RESERVES is not zero. hledger unfortunately allows this last eventuality. But you cannot usually present books to your auditor or the taxman or the regulator where the A+L+E=0 rule is broken. At the very least your auditor will have to fix your books before signing them off.

There is in most circumstances for almost all business little need to post in anything other than the base currency, as I have explained elsewhere you take the FX out of the books when you buy or sell something in another currency and you report the cost or proceeds in the local currency.

It is far easier to do FX (if one must) the proper way than the way hledger documents and which @edkedk99 favours. An example which persuasively demonstrates this follows subsequent posting:.

psb777 avatar Feb 03 '20 23:02 psb777

Read this file: explain.txt You'll have to rename the following two files removing the .txt suffix. memo.journal.txt dbl.journal.txt

psb777 avatar Feb 03 '20 23:02 psb777

Paul, thanks for the explanations, background and especially the nice clear examples. Are you an accountant ? Our wheels often grind slowly, so if you see no response for while don't think it means disagreement. It takes free brain cycles to digest and work on this, so your input is helpful and will be [re]read later if not immediately. By the way, we don't expect you to do all the work, but if you would be interested in working on a pull request, that can be very effective, since folks can try it out and report issues.

simonmichael avatar Feb 04 '20 00:02 simonmichael

With current hledger, I think I'm right in saying there's nothing stopping anyone from using more correct and disciplined journal entries, yes ? Stricter behaviour gives more error checking possibilities, but in practice I think we can detect errors pretty easily by other means. So I don't feel any burning urgency on this.

We have always planned a strict mode where we can apply more strict rules. This will be an optional extra at first, which is good for experimentation. Questions of changing default behaviour will come later, once we have more experience.

simonmichael avatar Feb 04 '20 00:02 simonmichael

I think I'll inline your example above, to encourage folks to try it out. (If you prefer to edit your comment, I'll delete this one.). Here's your

memo.journal (the old "wrong" way):

D USD 1,000.
commodity USD 1,000.
commodity EUR 1,000.

2008/1/1 opening balance
  assets:dollars         USD  100 
  equity:cash

P 2009-01-01 EUR USD 0.667

2009/1/1 FX purchase
  assets:euros           EUR  150 @@ 100   
  assets:dollars         USD -100         

P 2010-01-01 EUR USD 0.750

P 2011-01-01 EUR USD 0.800

2011/1/1 FX sale
  assets:euros           EUR -150 @@ 120  
  assets:dollars         USD  120

P 2012-01-01 EUR USD 0.950

dbl.journal (the new "right" way) (with comments added to show differences):

D USD 1,000.
commodity USD 1,000.
commodity EUR 1,000.

2008/1/1 opening balance
  assets:dollars         USD  100 
  equity:cash

P 2009-01-01 EUR USD 0.667

2009/1/1 FX purchase
  assets:euros           EUR  150  ; <-- no price
  assets:dollars         USD -100         
  equity:cash                      ; <-- extra posting

P 2010-01-01 EUR USD 0.750

P 2011-01-01 EUR USD 0.800

2011/1/1 FX sale
  assets:euros           EUR -150  ; <-- no price
  assets:dollars         USD  120
  equity:cash                      ; <-- extra posting

P 2012-01-01 EUR USD 0.950

and explain.txt (discussion of the above):

I wish to attempt to demonstrate conclusively why the style of FX dealing
or commodity exchange as documented in hledger and as permitted by hledger
is

1) is not just a less purist way way of doing things,
2) is not an easier way, it's more difficult,
3) produces less meaningful reports and
4) is just wrong.

Attached are two files.

The memo.journal file does the FX as per the hledger documentation, using
memorandum style accounting weirdly allowed by hledger only for commodity
trading.

The dbl.journal file does the FX correctly, properly doing double entry in
all the commodities all the time.

All will readily see there is practically the same amount of typing involved.
Or even less for the dbl file as for the memo file because the memo file
still requires extra adjustments to later fix the reserves, and I have not
provided suggestions for those messy fixes.

To illustrate why the memorandum style of FX accounting is so unsatisfactory
you just need to dirstly understand what each file identically models - a
conversion from dollars to euros and back again later at a different price -
and then run and contrast these two sets of balance reports.

hledger bal -f memo.journal   -X EUR
hledger bal -f memo.journal   -B
hledger bal -f memo.journal   -V
hledger bal -f memo.journal   

hledger bal -f dbl.journal   -X EUR
hledger bal -f dbl.journal   -B
hledger bal -f dbl.journal   -V
hledger bal -f dbl.journal   

You may wish to run these reports in intermediate dates too using the
following each in turn on both the memo and dbl examples.

--end=2008/07/01
--end=2009/07/01
--end=2010/07/01
--end=2011/07/01
--end=2012/07/01

Note that in the reports from the "memo" accounting even though a profit is
made by the buying and selling of currency this is not reflected in the
equity/reserves. 

Note how naturally everthing flows through with the "dbl" style, no effort at
all, and that the profit is reflected in the reserves, and there is no weird
hangover of non-existent extraneous balances.

simonmichael avatar Feb 04 '20 00:02 simonmichael

I'm going to practice the new style (what name communicates it - "balanced conversions" ?) in my 2020 journals to get some experience with it. I'd welcome reports from any other PTA users, especially if you convert an old journal.

hledger is first and foremost an accounting tool, but not only that. There's a long tradition of PTA users tracking time, calories, inventory and what not. We'll keep support for that kind of flexibility one way or another.

simonmichael avatar Feb 04 '20 00:02 simonmichael

Here's a vague misgiving I've had: "sure, we added an extra posting so the conversion amounts go there instead of on the main postings. But that can hold anything, so it doesn't really add any error checking (that hledger could report), does it ?"

If you write all the equity amounts explicitly, ok now it's explicit. But at the end of the year you have this equity account containing a zillion currencies, and does its balance tell you anything useful ? Is there really more error checking ?

Even now, still blissfully inexperienced with the new style, I do see some advantages.

  • It keeps the main accounts simple, involving just their native currency.
  • There's no need for @ transaction prices or the -B flag. (Ever ? Or, when are those still appropriate ?)
  • It gathers the balancing amounts from currency/commodity conversions into a single account, which you can exclude from reports, or inspect to get an overview of all conversions (and perhaps we can learn other useful things from it ?)

simonmichael avatar Feb 04 '20 01:02 simonmichael

Technically we have not added an extra posting. We take advantage of a short-cut feature of hledger to make TWO extra postings. I know you know that, but nevertheless, it's important.

So what we actually post in real life ought most fully properly be this:

2020/01/01 FX assets:cash:Citibank -11 USD equity:cash 11 USD assets:cash;Westpac 14 AUD equity:cash -14 AUD

Why are the equity:cash posting important other than for the technical reason that they allow the bookkeeping rule A+L+E=0 to be kept?

It's because it is not a technical rule, it's a real important legal rule! The equity/reserves/capital ledger shows what is the property of the shareholders/partners/householder. The assets ledger shows what is owed to the business/entity for which the accounts are being performed. The 14 USD isn't in our possession, it's at the bank! The 11 USD is no longer owed us by the bank. Hence the posting in the assets ledger. Why the postings in the equity ledger? Well, why any postings in the equity ledger? It shows what the enterprise owes its owners. Well, what the enterprise owes its owners is 11 USD less than it did before, and 14 AUD more than it did before. And as long as you book USD OR BoeingCommonStock or IBM as a commodity in the Assets ledger you MUST reflect that in the equity ledger.

A way around this is to only book the USD value of the stocks and currencies in the assets ledger. But then how will you automatically book P&L upon a price change, you will have to do it manually. Whereas, as per my example, if we swap back from AUD into USD at an improved price thusly

2020/01/01 FX assets:cash:Citibank 13 USD equity:cash -13 USD assets:cash;Westpac -14 AUD equity:cash 14 AUD

then our USD 2 profit is plainly shown in increased assets at Citibank matched by an increased liability to our shareholders in the equity ledger. That is how it should be. The business no longer owns any AUD, and the AUD balance has disappeared from the books everywhere.

But say it had not. Say we didn't sell the AUD, or that we bought more, or sold half, then the noise/nonsense postings are neither noise nor nonsense, they reflect the ongoing change in the reserves position of the business. It's not noise, it's information!

You ask what do you do with the accumulating FX postings in the equity ledger. The same as you do with the accumulating postings in the expenses ledger. At some point you post the balance to a year-end account, or you do what I do: I leave them exactly where they are: The accounts are a record of your business.

I haven't been using hledger long. I will probably put all the postings in a 2020.journal file which I will include from the main hledger.journal file. This will have several advantages. It will mean I won't mistakenly make changes to historical data, and it keeps the current file short.

I really like hledger, by the way! Thank you.

[email protected]

On Tue, 4 Feb 2020 at 01:03, Simon Michael [email protected] wrote:

Here's a vague misgiving I've had: "sure, we added an extra posting so the conversion amounts go there instead of on the main postings. But that can hold anything, so it doesn't really add any error checking (that hledger could report), does it ?"

If you write all the equity amounts explicitly, ok now it's explicit. But at the end of the year you have this equity account containing a zillion currencies, and does its balance tell you anything useful ? Is there really more error checking ?

Even now, still blissfully inexperienced with the new style, I do see some advantages. It keeps the main accounts simple, involving just their native currency. There's no need for @ transaction prices or the -B flag. (Ever ? Or, when are those still appropriate ?) It gathers the balancing amounts from currency/commodity conversions into a single account, which you can exclude from reports, or inspect to get an overview of all conversions (and perhaps we can learn other useful things from it ?)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/simonmichael/hledger/issues/1177?email_source=notifications&email_token=ABXVLL3HNHW4LVKGTW7UHILRBC5HTA5CNFSM4KHVV562YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKV7C2Y#issuecomment-581693803, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABXVLL63OW57FRSOGOCZBOLRBC5HTANCNFSM4KHVV56Q .

psb777 avatar Feb 04 '20 02:02 psb777

What does the accumulation of posting in the equity:cash account tell you? The balance of each currency tells you how much of each currency is owed the shareholders/partners/householders should you wind the firm/business/marriage up.

What is the error checking? The std double entry error checking, but in addition the auditors will check that the assets are in the bank, the vault, the aircraft hangar, at the share custodian, and that the liabilities similarly, and that the shareholders are happy with the value of the company, this is the size of the reserve ledger.

For extra paractical error checking from time to time you put a dated reconciled balance assertion in for all the main accounts within assets and liabilities and reserves and if anyone makes a backdated posting then hledger will tell you.

I'm unsure it's a good think that hledger let's you not type the amount twice. Any typo should go detected. I try and make all my postings explicit as its best to force detection of a typo: I like it that this is rejected.

2222/22/22 xx:yy 12.34 zz:aa -12.35

[email protected]

On Tue, 4 Feb 2020 at 01:03, Simon Michael [email protected] wrote:

Here's a vague misgiving I've had: "sure, we added an extra posting so the conversion amounts go there instead of on the main postings. But that can hold anything, so it doesn't really add any error checking (that hledger could report), does it ?"

If you write all the equity amounts explicitly, ok now it's explicit. But at the end of the year you have this equity account containing a zillion currencies, and does its balance tell you anything useful ? Is there really more error checking ?

Even now, still blissfully inexperienced with the new style, I do see some advantages. It keeps the main accounts simple, involving just their native currency. There's no need for @ transaction prices or the -B flag. (Ever ? Or, when are those still appropriate ?) It gathers the balancing amounts from currency/commodity conversions into a single account, which you can exclude from reports, or inspect to get an overview of all conversions (and perhaps we can learn other useful things from it ?)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/simonmichael/hledger/issues/1177?email_source=notifications&email_token=ABXVLL3HNHW4LVKGTW7UHILRBC5HTA5CNFSM4KHVV562YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKV7C2Y#issuecomment-581693803, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABXVLL63OW57FRSOGOCZBOLRBC5HTANCNFSM4KHVV56Q .

psb777 avatar Feb 04 '20 02:02 psb777

Great! I'm learning. For most-correct accounting, maintain the accounting equation within each commodity. Thanks Paul!

simonmichael avatar Feb 04 '20 02:02 simonmichael

I'm a software techie, or was, many years ago. We ran a business writing systems for stockbrokers and the systems had at their heart a multi-security double entry accounting system. I've thought more about the technical aspects of bookkeeping, about bookkeeping as maths and logic, than most accountants.

Hledger incorporates so much of what we did, and it does it so well. We used relational databases (we needed multi-user concurrency) but hledger is perfect for my own purposes, managing my investments and a few foreign bank accounts.

I love the idea of getting my head around Haskell but GitHub I'm unsure I'll ever be able to cope with.

I'm not sure I'll be able to do any Haskell programming but there are many ways to contribute and I hope I do, I haven't pissed you off. Yet!

:-)

On Tue, 4 Feb 2020, 12:21 am Simon Michael, [email protected] wrote:

Paul, thanks for the explanations, background and especially the nice clear examples. Are you an accountant ? Our wheels often grind slowly, so if you see no response for while don't think it means disagreement. It takes free brain cycles to digest and work on this, so your input is helpful and will be [re]read later if not immediately. By the way, we don't expect you to do all the work, but if you would be interested in working on a pull request, that can be very effective, since folks can try it out and report issues.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/simonmichael/hledger/issues/1177?email_source=notifications&email_token=ABXVLL7BCKNQQLXU6YTM3IDRBCYINA5CNFSM4KHVV562YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKV4S5Y#issuecomment-581683575, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABXVLL7T7D3JDKLLMF7HZW3RBCYINANCNFSM4KHVV56Q .

psb777 avatar Feb 04 '20 02:02 psb777

Oh, fantastic! Welcome.

simonmichael avatar Feb 04 '20 03:02 simonmichael

@psb777

I ran your examples and detected you are not following hledger's website instructions in your memo.journal file, and this mistake causes your reports to print wrong results.

The '@' or '@@' symbol doesn't mean 'at', as it is commonly understood in common language. In PTA context, '@' means costing.

So, in 2011, you should have informed that your cost for those EUR 150 was USD 100, and not USD 120.

So, to follow hledger's official instructions, memo.ledger should be like below

D USD 1,000.
commodity USD 1,000.
commodity EUR 1,000.

2008/1/1 opening balance
  assets:dollars         USD  100 
  equity:cash

P 2009-01-01 EUR USD 0.667

2009/1/1 FX purchase
  assets:euros           EUR  150 @@ 100   
  assets:dollars         USD -100         

P 2010-01-01 EUR USD 0.750

P 2011-01-01 EUR USD 0.800

2011/1/1 FX sale
  assets:euros           EUR -150 @@ 100  ; Cost is 100, not 120  
  assets:dollars         USD  120
  Income:Fx Income                        ; The difference is your FX profit

P 2012-01-01 EUR USD 0.950

If you ran the suggested reports now, they will both give the same results. The difference seems to be that in memo.journal's case, the Income is explicit, while in db.journal the equity automatically increase or decrease.

Even arriving to the correct result, db.journal approach should not be suggested because it also changes the meaning of the '@' symbol, from cost to price, which is hard to spot in the file because those values are implicit.

I would say that memo.journal again is more compliant with accounting standards, which demands explicit income in the Balance Sheet. In db.journal, you would need to calculate manually the difference by looking at the evolution

edkedk99 avatar Feb 04 '20 12:02 edkedk99

Thank you @edkedk99, very interesting also. I always pronounce @/@@ as "at", but you make it clear that it can be used to mean two different things:

  1. when buying or selling: the cost or sale price in the current transaction, ie https://hledger.org/journal.html#transaction-prices

or

  1. when selling: the cost at which this asset/liability was acquired, ie its cost basis

In hledger, that is; I think Ledger has different syntax for each case (@/@@ vs. {= }, or something similar).

I'm not sure this is made clear anywhere on hledger.org - if it is, please point me to it ?

If you ran the suggested reports now, they will both give the same results.

I won't believe that until I see your commands and output. :) I get different results from all three journals here.

simonmichael avatar Feb 04 '20 15:02 simonmichael

$ hledger bal -f memo2.journal -BV hledger: "/b1/home/psb/PsbPrivate/hledger/tutfx/memo2.journal" (lines 19-21) could not balance this transaction (real postings are off by USD 20) 2011/01/01 FX sale assets:euros EUR -150 @@ USD 100 assets:dollars USD 120

[email protected]

On Tue, 4 Feb 2020 at 12:38, edkedk99 [email protected] wrote:

@psb777 https://github.com/psb777

I ran your examples and detected you are not following hledger's website instructions in your memo.journal file, and this mistake causes your reports to print wrong results.

The '@' or '@@' symbol doesn't mean 'at', as it is commonly understood in common language. In PTA context, '@' means costing.

So, in 2011, you should have informed that your cost for those EUR 150 was USD 100, and not USD 120.

So, to follow hledger's official instructions, memo.ledger should be like below

D USD 1,000. commodity USD 1,000. commodity EUR 1,000.

2008/1/1 opening balance assets:dollars USD 100 equity:cash

P 2009-01-01 EUR USD 0.667

2009/1/1 FX purchase assets:euros EUR 150 @@ 100 assets:dollars USD -100

P 2010-01-01 EUR USD 0.750

P 2011-01-01 EUR USD 0.800

2011/1/1 FX sale assets:euros EUR -150 @@ 100 ; Cost is 100, not 120 assets:dollars USD 120 Income:Fx Income ; The difference is your FX profit

P 2012-01-01 EUR USD 0.950

If you ran the suggested reports now, they will both give the same results. The difference seems to be that in memo.journal's case, the Income is explicit, while in db.journal the equity automatically increase or decrease.

I would say that memo.journal again is more compliant with accounting standards, which demands explicit income in the Balance Sheet. In db.journal, you would need to calculate manually the difference by looking at the evolution

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/simonmichael/hledger/issues/1177?email_source=notifications&email_token=ABXVLL4RCPRPOU3FODQ6YP3RBFOVDA5CNFSM4KHVV562YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKXPLMY#issuecomment-581891507, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABXVLL5PTCFTDY3R3572A43RBFOVDANCNFSM4KHVV56Q .

psb777 avatar Feb 04 '20 16:02 psb777

@psb777

You forgot the the last line -> Income:Fx Income

2011/1/1 FX sale
  assets:euros           EUR -150 @@ 100  ; Cost is 100, not 120  
  assets:dollars         USD  120
  Income:Fx Income                        ; The difference is your FX profit

edkedk99 avatar Feb 04 '20 17:02 edkedk99

@simonmichael

My modified memo.journal

D USD 1,000.
commodity USD 1,000.
commodity EUR 1,000.

2008/1/1 opening balance
  assets:dollars         USD  100 
  equity:cash

P 2009-01-01 EUR USD 0.667

2009/1/1 FX purchase
  assets:euros           EUR  150 @@ 100   
  assets:dollars         USD -100         

P 2010-01-01 EUR USD 0.750

P 2011-01-01 EUR USD 0.800

2011/1/1 FX sale
  assets:euros           EUR -150 @@ 100  ; Cost is 100, not 120  
  assets:dollars         USD  120
  Income:Fx Income                        ; The difference is your FX profit

P 2012-01-01 EUR USD 0.950

hledger bal -f memo.journal -X EUR

             EUR -21  Income:Fx Income
             EUR 126  assets:dollars
            EUR -105  equity:cash
--------------------
                   0

hledger bal -f memo.journal -B

             USD -20  Income:Fx Income
             USD 120  assets:dollars
            USD -100  equity:cash
--------------------
                   0

hledger bal -f memo.journal -V

             USD -20  Income:Fx Income
             USD 120  assets:dollars
            USD -100  equity:cash
--------------------
                   0

hledger bal -f memo.journal

             USD -20  Income:Fx Income
             USD 120  assets:dollars
            USD -100  equity:cash
--------------------
                   0

edkedk99 avatar Feb 04 '20 17:02 edkedk99

@simonmichael

I'm not sure this is made clear anywhere on hledger.org - if it is, please point me to it ?

I think documentation makes it clear. One problem is that the symbol '@' means 'at' in regular speech, so a regular user when adding a transaction may relate the symbol to the usual meaning, and not the docs meaning. Maybe we could emphasize this difference in the docs

See in https://hledger.org/track-investments.html

You end up with the correct amount in your depot. At some point, however, you will have to report the capital gain that you realized with your sale. This gain is currently invisible. In fact, we have violated the double-entry principle and created money out of nowhere.

Let’s report our sale in a different way.

2017/1/4 sell shares at $250
  assets:shares         -10 TSLA @ $200  ; cost basis (must be tracked by user!)
  assets:depot          $2500            ; cash proceeds
  revenue:capital_gains                  ; deduce profit

See: cost basis (must be tracked by user!)

edkedk99 avatar Feb 04 '20 17:02 edkedk99

@edkedk99 it's not critical, but if you have time, for the sake of clarity, could you show what you meant by "If you ran the suggested reports now, they will both give the same results." Here I show my results with your journal and @psb777's.

~/src/hledger/examples/pb-1177$ hledger bal -f edk.journal -X EUR
             EUR -21  Income:Fx Income
             EUR 126  assets:dollars
            EUR -105  equity:cash
--------------------
                   0
~/src/hledger/examples/pb-1177$ hledger bal -f edk.journal -B
             USD -20  Income:Fx Income
             USD 120  assets:dollars
            USD -100  equity:cash
--------------------
                   0
~/src/hledger/examples/pb-1177$ hledger bal -f edk.journal -V
             USD -20  Income:Fx Income
             USD 120  assets:dollars
            USD -100  equity:cash
--------------------
                   0
~/src/hledger/examples/pb-1177$ hledger bal -f edk.journal 
             USD -20  Income:Fx Income
             USD 120  assets:dollars
            USD -100  equity:cash
--------------------
                   0
~/src/hledger/examples/pb-1177$ hledger bal -f dbl.journal -X EUR
             EUR 126  assets:dollars
            EUR -126  equity:cash
--------------------
                   0
~/src/hledger/examples/pb-1177$ hledger bal -f dbl.journal -B
             USD 120  assets:dollars
            USD -120  equity:cash
--------------------
                   0
~/src/hledger/examples/pb-1177$ hledger bal -f dbl.journal -V
             USD 120  assets:dollars
            USD -120  equity:cash
--------------------
                   0
~/src/hledger/examples/pb-1177$ hledger bal -f dbl.journal
             USD 120  assets:dollars
            USD -120  equity:cash
--------------------
                   0

simonmichael avatar Feb 04 '20 17:02 simonmichael

See in https://hledger.org/track-investments.html

That's a useful doc, thanks. (Tier 2 doc, could use an update, but explains the two meanings nicely.)

simonmichael avatar Feb 04 '20 17:02 simonmichael

@simonmichael ,

If you ran the suggested reports now, they will both give the same results.

It means that in the 4 reports if you sum 'equity:cash' and 'Income:Fx Income' in edk.journal, the value is the same as in 'equity.cash' from dbl.journal alone.

In fact, I should have said that equity will be the same after you transfer profits to accumulated profits in an equity subaccount

edkedk99 avatar Feb 04 '20 18:02 edkedk99

@edkedk99, I really don't mind how anybody does their accounting, I'm merely arguing (1) hedger should not by default allow the double entry bookkeeping rules to be broken and (2) that the official documentation should promote the better and correct method, the one which always leaves the balance sheet in balance.

Comparing the documented method, which I perhaps unfairly call "your" method, with the rules compliant method, which I unfairly call "my" method, how would we choose one over the other? What are the pros and cons, one method over the other? I cannot think of any advantage of "your" method save that that is how some people use hledger, and we ought to provide a compatibility option so as to continue to support the documented method, even if the documentation is to change. The other way, "my" way, has these advantages, minor and major:

(1) Character count. Your method requires " @@ 100.00" twice, plus "income:fx" once, 29 characters. My method requires "income:fx" twice, 18 characters.

(2) Your method requires that you go and look up what you paid for the commodity when you sell it. This is an unnecessary step in my method. When selling a proportion of it you will need to calculate the cost, if it is the "@@" convention you've used.

(3) In your method the balance sheet remains out of balance, breaking the most important rule in double entry bookkeeping, A+L+E=0, forever, or until exactly the entire amount of the FX is sold, which will not ordinarily happen, the FX having been obtained for some purpose other than speculation. A+L+E will never, in practical terms, ever be zero again.

(4) As the price of the FX purchased changes over time the unrealised profit does not appear anywhere easily reported by hledger except as the un-named imbalance in the balance sheet. You cannot drill down into this imbalance in the UI. And ever so weirdly the display of

hledger-ui -f your-way-with-equity-fx-not-income-fx.journal --end=2010/07/01 -V

is this:

assets:dollars 0
assets:euros USD 112
equity:cash USD -100
equity:fx 0

whereas this command

hledger-ui -f my-way-using-equity-fx-not-equity-cash.journal --end=2010/07/01 -V

displays this:

assets:dollars         0
assets:euros     USD 112
equity:cash       USD -100
equity:fx            USD -12

Paul

psb777 avatar Feb 04 '20 20:02 psb777

@psb777

I came to the conclusion that we are discussing different approaches. I don't expect my report to balance with -V option, only with -B. But that is my personal take. As you mentioned earlier, you are new to hledger, so am I. Let's see what the developer and other users think about all of this.

edkedk99 avatar Feb 04 '20 20:02 edkedk99

Probably a good next step from this will be a concise faq/how-to on hledger.org, showing these different approaches and summarising pros/cons. Next after that, I'd be in favour of a -s/--strict flag that disables the automatic commodity conversion that happens somewhere around here.

simonmichael avatar Feb 04 '20 20:02 simonmichael

Yes, I agree with you both, @edkedk99 and @simonmichael. It's what works for you that counts, There is nothing wrong with hledger as it stands in version 1.16 save for my view that it should require a --compatible flag to work the old way rather than a --strict flag to behave, according to me, correctly. Hledger is great, very happy to have found it. Maybe an intermediate fix is a dispassionate documentation enhancement as suggested.

Suggestion: That there is an imbalance introduced by the @@ method ought generate a WARNING.

psb777 avatar Feb 04 '20 21:02 psb777

One question I have is how @psb777 's method interacts with the -B flag. It may very well be that this flag is not a wise way to display the desired information in any case, but given the following transaction

2000-01-01 Buy widgets
  expenses:widgets   1.00 USD @@ 1.50 CAD
  assets:cash       -1.50 CAD

how would you generate a report in which widget expenses were 1.50 CAD after converting it to this form?

2000-01-01 Buy widgets
  expenses:widgets   1.00 USD
  assets:cash       -1.50 CAD
  equity:fx         -1.00 USD
  equity:fx          1.50 CAD

Xitian9 avatar Feb 27 '20 12:02 Xitian9

Good question @Xitian9. -B or --value=cost use the posting's "transaction price". How do we infer the transaction price for each posting in the journal entry above ? And in general ?

simonmichael avatar Feb 27 '20 16:02 simonmichael

(Maybe we already do that ? print -x on a bunch of such entries should be informative.)

simonmichael avatar Feb 27 '20 16:02 simonmichael

Some updates/next steps related to this:

  • I wrote a newer https://hledger.org/investments.html tutorial touching on this issue
  • Let's implement conversion rate inference from a balanced @-free transaction - it seems possible and would allow -B and --infer-value to work without the need for @ notation
  • Let's try changing how we store @ entries, adding "equity:conversion" postings where needed, so that they are just syntactic sugar for the balanced @-free form. Perhaps print --explicit would show the balanced form. This could be quite disruptive but let's explore it.
  • Let's clarify whether we need separate notations for expressing current conversion rate and original cost basis, like Ledger/Beancount's @ and {}, or some improvement on that, and/or if we can do something simpler using accounts as in the above tutorial.
  • All help welcome. I have some bounty money which I'll apply here too.

simonmichael avatar Jun 23 '20 14:06 simonmichael

$55 bounty applied, via https://www.bountysource.com/issues/87085783-basic-double-entry-rules-broken-in-some-permitted-fx-transactions

simonmichael avatar Jun 23 '20 14:06 simonmichael

Very interesting discussion. I wanted to add some other real-life examples for the use of multi-currency trading accounts. A very simple example:

2020-07-08 Name.com
    Expenses:Tech:Domains                     USD 12.99
    Equity:Trading:Currency:USD:INR          USD -12.99   ; @@  ₹-975.20
    Equity:Trading:Currency:INR:USD             ₹975.20   ; @@ USD 12.99
    Liabilities:Credit Card:YES                ₹-975.20

I use Equity:Trading to capture all commodity/currency conversions. Currencies (non-investment) go under Equity:Trading:Currency. And then the currency tuples: USD:INR for USD values of INR conversions, and INR:USD for INR values of USD conversions.

If I use price declarations, then I can find out the net unrealized gain/loss for that currency pair by querying the balance of the currency tuples:

hledger bal inr:usd usd:inr --value=now

Different sub-accounts of Equity:Trading are used for different kinds of trades. So, if I was engaging in forex trading for investment purposes (which need to be accounted for on FIFO basis), I use Equity:Trading:Investment:Currency and its sub-accounts, with dated sub-accounts for lots, instead of Equity:Trading:Currency. I also have sub-accounts for a trades involving pension scheme units (with pairs such as Equity:Trading:NPS:SM001003:INR and Equity:Trading:NPS:INR:SM001003), and mutual fund units (with pairs such as Equity:Trading:MF:INF109K01AF8:INR and Equity:Trading:MF:INR:INF109K01AF8).

Organizing the trades such tuples make it very easy to query unrealized gains at any point in time.

The shortcoming of this approach, of course, is that hledger doesn't know the cost basis. It either infers the cost basis from an unbalanced transaction, or it is told the cost basis by using @ / @@, etc. But explicitly telling hledger the cost basis doesn't work if your transactions are balanced, as the example above would be.

Further, inferring the cost basis can be difficult since sometimes multiple trading accounts show up in a single transaction, as in this example, where units in 3 different pension schemes are being bought with a single transfer from my bank to my pension account.

2017-03-31 NPS | Contribution FY2016  ; tax:deduction:80c:80ccd1b:nps
    Assets:Investment:NPS:E             "SM001003" 1215.5512
    Assets:Investment:NPS:C              "SM001004" 644.0643
    Assets:Investment:NPS:G              "SM001005" 464.0931
    Expenses:Financial:Bank:SBI                      ₹144.00
    Equity:Trading:NPS:SM001003:INR    "SM001003" -1215.5512
    Equity:Trading:NPS:INR:SM001003               ₹25,000.00
    Equity:Trading:NPS:SM001004:INR     "SM001004" -644.0643
    Equity:Trading:NPS:INR:SM001004               ₹15,000.00
    Equity:Trading:NPS:SM001005:INR     "SM001005" -464.0931
    Equity:Trading:NPS:INR:SM001005               ₹10,000.00
    Assets:Savings:SBI                           ₹-50,144.00

Some thoughts that may help with the implementation:

  1. Equity:Trading or Equity:Conversion should always show up in pairs.
  2. Sometimes multiple pairs of trading accounts will show up in a single transaction.
  3. Inferring conversion rates (for --value=cost reports) works better if users use currency tuples to make it clear which two trading accounts are linked to each other.
  4. If not inferring the cost basis, then allowing users to provide explicit conversion rates (in the main posting itself, or in the comments to the posting) should be permitted, to avoid confusion as to which trading account pairs belong together.
  5. For future discussion (for implementation of lots, etc.): Lots sometimes matter (investment) and sometimes don't (currency conversion for spending), but the way conversion inferences is implemented should support both.

For what it's worth, Martin Blais of Beancount says that Beancount will eventually shift towards trading accounts as "the correct way" for accounting for currency gains:

The correct way to account for gains resulting in varying rates over time is to use the "trading accounts" method linked somewhere else on this list, not the cost basis. Eventually Beancount will make that method the default method to balance currency conversions, and then it should be possible.

the-solipsist avatar Jan 29 '21 21:01 the-solipsist

As a first step to improving this issue, would it be reasonable to have the current price notation become shorthand for an fx equity account? I'm imagining the following transaction would be expanded as follows:

2000-01-01 Buy widgets
  expenses:widgets   1.00 USD @@ 1.50 CAD
  assets:cash       -1.50 CAD

Without cost conversion:

2000-01-01 Buy widgets
  expenses:widgets   1.00 USD
  assets:cash       -1.50 CAD
  equity:fx         -1.00 USD
  equity:fx          1.50 CAD

or possibly with more specific account names.

2000-01-01 Buy widgets
  expenses:widgets              1.00 USD
  assets:cash                  -1.50 CAD
  equity:conversion:USD:CAD    -1.00 USD
  equity:conversion:CAD:USD     1.50 CAD

With cost conversion:

2000-01-01 Buy widgets
  expenses:widgets   1.50 CAD
  assets:cash       -1.50 CAD

Xitian9 avatar Apr 26 '21 05:04 Xitian9

A potential issue with the ‘more specific account names’ idea above: commodity symbols are allowed to have two spaces in them, which would make them invalid in account names. I imagine collapsing multiple spaces to a single space would solve this problem, and be unlikely to cause real-world problems.

Xitian9 avatar Apr 26 '21 05:04 Xitian9

We always must have a link to Selinger in these discussions; here's one from #hledger today: https://www.mathstat.dal.ca/~selinger/accounting/tutorial.html#3

simonmichael avatar Jun 16 '21 01:06 simonmichael

Some thoughts that may help with the implementation:

  1. Equity:Trading or Equity:Conversion should always show up in pairs.
  2. Sometimes multiple pairs of trading accounts will show up in a single transaction.
  3. Inferring conversion rates (for --value=cost reports) works better if users use currency tuples to make it clear which two trading accounts are linked to each other.
  4. If not inferring the cost basis, then allowing users to provide explicit conversion rates (in the main posting itself, or in the comments to the posting) should be permitted, to avoid confusion as to which trading account pairs belong together.
  5. For future discussion (for implementation of lots, etc.): Lots sometimes matter (investment) and sometimes don't (currency conversion for spending), but the way conversion inferences is implemented should support both.

I should have worded point # 4 a bit more strongly: allowing users a means to provide explicit conversion rates MUST be permitted. Otherwise, the complex (pension) example I quoted in https://github.com/simonmichael/hledger/issues/1177#issuecomment-770057357 wouldn't work.

I think lots, gains/losses, and commodity conversions are the three hardest things to get right.

the-solipsist avatar Oct 28 '21 13:10 the-solipsist

Folks interested in this issue should also check out #1554. I have posted an attempted summary of it, with some open questions, at https://hledger.org/conversion2.html#xitians-1554 .

simonmichael avatar Nov 29 '21 03:11 simonmichael