Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

close --retain, multicurrency balances, and balance assertions

8 views
Skip to first unread message

J. B. Rainsberger

unread,
Apr 15, 2025, 3:50:11 PMApr 15
to hledger
Hi, folks. I am not sure what to do here, so I need your advice.

I am generating a "retain earnings" entry for my accountants. I have multicurrency balances and my home currency is CAD (for ease of reference). I am struggling because I appear to be stuck between two options that both don't work:

1. run `close --retain --value-"then,CAD"`, then fail the balance assertion in the first multicurrency balance, since the CAD balance is not 0, even though the "then value" of the account overall is 0 CAD.
2. run `close --retain` without currency conversion, pass balance assertion, but then have non-zero "then value" balances in Revenue and Expense accounts.

Option 1 causes me to be stuck and option 2 will cause my accountants to balk.

I tried to read the relevant section of the documentation, but it's unclear to me how to make balance assertions pass in multicurrency balances where, for example, EUR 4 + CAD -6 = 0 when 1 EUR = 1.5 CAD.

One possibility is to trust `close --retain` and ignore the balance assertions, but that seems fundamentally unsafe. Presumably, those balance assertions are there to protect me.

I'm open to suggestion and prepared to answer questions to get to the bottom of this. For the sake of unblocking my accountants, I can ignore the balance assertions and carry on, but that seems risky and to invite failure.

Thanks,
jbrains


J. B. Rainsberger

unread,
Apr 15, 2025, 3:54:58 PMApr 15
to hledger
To be clear, in option 2, the non-zero "then value" balances arise from the timing difference in exchange rate between when a foreign currency transaction was posted and the value of that currency on the date of the Retained Earnings entry. That might have been obvious, but I thought I'd clarify it anyway. The accountants would balk, because the converted CAD balances in the Revenue and Expense accounts would appear to be not 0.

Simon Michael

unread,
Apr 15, 2025, 6:08:51 PMApr 15
to J. B. Rainsberger, hle...@googlegroups.com
My general guess is the right thing is to convert all to your base currency somewhere. But can you share a minimal example ? 
--
You received this message because you are subscribed to the Google Groups "hledger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hledger+u...@googlegroups.com.

J. B. Rainsberger

unread,
Apr 16, 2025, 11:03:17 AMApr 16
to hle...@googlegroups.com
Thanks for the idea. I suppose I can use the `close --retain` command twice: once to generate all the transactions in foreign currencies, then once again to generate the transactions in CAD/home currency. I can then splice the two together and they should balance with no Exchange Gain/Loss, since hledger calculated the amounts with the fx rates in effect on that day. I can be satisfied with that.

I was mostly concerned about hardcoding fx rates in transactions and this seems to avoid that, so let's see what happens when I try...

Meantime, I'll try to build a minimal example. I've set a reminder.

Thanks.
--
J. B. (Joe) Rainsberger :: tdd.training :: jbrains.ca ::
blog.thecodewhisperer.com

Replies from this account routinely take a few days, which allows me to reply thoughtfully. I reply more quickly to messages that clearly require answers urgently. If you need something from me and are on a deadline, then let me know how soon you need a reply so that I can better help you to get what you need. Thank you for your consideration.

You received this message because you are subscribed to a topic in the Google Groups "hledger" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/hledger/y9RiUixwD5Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to hledger+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/hledger/86a5d4ab-96ef-4d6f-b2dd-901270454dde%40app.fastmail.com.

J. B. Rainsberger

unread,
Apr 16, 2025, 11:27:09 AMApr 16
to hle...@googlegroups.com
It looks like I should generate the Retained Earnings entry using `--value="end,CAD"` rather than my usual `--value="then,CAD"`, in order to convert all the balances on the year-end date and avoid any timing differences in the value of the foreign currencies. Does that sound right to you? It seems to balance as expected.

Thanks,
--
J. B. (Joe) Rainsberger :: tdd.training :: jbrains.ca ::
blog.thecodewhisperer.com

Replies from this account routinely take a few days, which allows me to reply thoughtfully. I reply more quickly to messages that clearly require answers urgently. If you need something from me and are on a deadline, then let me know how soon you need a reply so that I can better help you to get what you need. Thank you for your consideration.

J. B. Rainsberger

unread,
Apr 16, 2025, 11:43:44 AMApr 16
to hle...@googlegroups.com
OK, no. Sorry for thinking through this in real time in this forum, but that's how this kind of thing goes...

When I run `close --retain --value="then,CAD"`, I get what I believe is the correct CAD balance in each Revenue and Expense account, based on the market value of each currency on the date of each transaction. This computes the Equity:Retained Earnings amount for the year correctly.

When I run `close --retain` without converting the currency, I get a posting that adjusts the balance of each Revenue and Expense account to 0 (in all currencies), but due to the timing differences in the market value of each currency during the fiscal year, this computes a different CAD value for Equity:Retained Earnings, which makes it look like an Exchange Gain/Loss that I'm not expecting. (It happens to be about 438 CAD in my case.)

So how do I compensate for this without harcoding fx exchange rates in the transactions? Maybe this is how I learn about some feature of hledger that I haven't had to deal with yet. :)

I believe what I want to do is to stipulate in my "retain earnings" posting that the CAD amount for "Retained Earnings" balances the multicurrency transaction (even though no market value calculation makes it match: not "then", not "now", not "end") and to infer the cost of the currency from that. Do I have to hardcode that cost in the posting? Is there some implicit posting magic that I can use here? It could make perfect sense to hardcode the cost in the posting, but I'd rather avoid that in general.

Thanks,
--
J. B. (Joe) Rainsberger :: tdd.training :: jbrains.ca ::
blog.thecodewhisperer.com

Replies from this account routinely take a few days, which allows me to reply thoughtfully. I reply more quickly to messages that clearly require answers urgently. If you need something from me and are on a deadline, then let me know how soon you need a reply so that I can better help you to get what you need. Thank you for your consideration.

Simon Michael

unread,
Apr 16, 2025, 1:17:41 PMApr 16
to hle...@googlegroups.com
Good to follow another PTA’s explorations - we can all learn from such posts. As for concrete help though it’s hard for me to think this through without a concrete example to test against, I would be quite likely to answer the wrong questions.

J. B. Rainsberger

unread,
Apr 25, 2025, 12:45:30 PMApr 25
to hle...@googlegroups.com
I finally found a quiet moment to do this.


Please let me know how well `notes.md` describes the problem as I am experiencing it.

Thanks!
--
J. B. (Joe) Rainsberger :: tdd.training :: jbrains.ca ::
blog.thecodewhisperer.com

Replies from this account routinely take a few days, which allows me to reply thoughtfully. I reply more quickly to messages that clearly require answers urgently. If you need something from me and are on a deadline, then let me know how soon you need a reply so that I can better help you to get what you need. Thank you for your consideration.

Simon Michael

unread,
Apr 26, 2025, 12:31:27 AMApr 26
to hle...@googlegroups.com
Long story short: the "close to native currency case works for me" - if one file includes the other as a subfile (it doesn't matter which way round).

Then, hledger bse -V also works (valuing all on the same date). I think that's the only way to balance the accounting equation, since otherwise there's price skew as you say.

Why ? Balance assertions can span a hierarchy of files, but not sibling files.

Why ?  I think it's by design/necessity, to keep reports stable. I have just now expanded the relevant section in the docs: https://hledger.org/dev/hledger.html#assertions-and-multiple-files

Let me know what you think.

This was a very nice repro (which I needed, to get traction). Sorry this one "feature" cost you so much time ...

Best
--
You received this message because you are subscribed to the Google Groups "hledger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hledger+u...@googlegroups.com.

Marco van Hulten

unread,
Apr 26, 2025, 7:28:02 AMApr 26
to hle...@googlegroups.com
Hi all—

I could not easily follow the discussion, probably because I have never
used 'close --retain'. However, assertions I use very often and I want
to understand (and help improve) the added documentation section:

> Assertions and multiple files
> If an account has transactions appearing in multiple files, balance
> assertions can still work - but only if those files are in a
> parent-child relationship, using include directives.
>
> If the same files are siblings, the assertions will not work. For
> example if you specify them with two -f options on the command line,
> the assertions in one will not see the balances from the other.

I have tested this and it indeed complained. Specifically, the
complaint was that the transaction is unbalanced (giro 10 USD = 10
USD)! In one ledger file I add 10 USD to an account and in another
ledger file I have this entry with a later date:

2025-04-27 * assertion
giro = 10 USD

For an assertion there is nothing to balance, right?

> But also, if a parent file includes the two subfiles with two
> side-by-side include directives, this too will fail (I think I have
> that right). Assertions in one subfile will not see the balances from
> the other.

The attached example works for me: main.ledger includes sub1.ledger and
sub2.ledger "side-by-side". All of them include asserts that succeed.
I ran 'hledger -f main.ledger check -s'.

> To work around this, arrange your files in parent child relationships
> with include. Eg make one subfile include the other (it doesn't matter
> which way round).

And so, I have doubts if this is needed. Moreover, I hope it is not
needed, because a typical use of combining multiple files has some
side-by-side inclusions (and making this a deep tree of sub-includes is
awkward).

> …

—Marco
main.ledger
sub1.ledger
sub2.ledger

Simon Michael

unread,
Apr 26, 2025, 7:49:33 AMApr 26
to hle...@googlegroups.com
Thanks for that Marco. Indeed I have doubts about what I wrote. Either this is a bit subtle and hard to reproduce or (ideally) I made a mistake and confused myself. Perhaps some formal tests are needed.

J. B. Rainsberger

unread,
Apr 27, 2025, 10:18:42 AMApr 27
to hle...@googlegroups.com
On Sat, Apr 26, 2025 at 2:01 AM Simon Michael <si...@joyful.com> wrote:
Long story short: the "close to native currency case works for me" - if one file includes the other as a subfile (it doesn't matter which way round).

Then, hledger bse -V also works (valuing all on the same date). I think that's the only way to balance the accounting equation, since otherwise there's price skew as you say.

Why ? Balance assertions can span a hierarchy of files, but not sibling files.

Why ?  I think it's by design/necessity, to keep reports stable. I have just now expanded the relevant section in the docs: https://hledger.org/dev/hledger.html#assertions-and-multiple-files

Let me know what you think.

First, thank you for looking.

Next, two things.

Thing 1. "Eg it would be frustrating if tomorrow all your balance assertions broke because you wrote command line arguments in a different order. (Discussion welcome.)"

If hledger guaranteed that the sequence of processing sibling files is stable, then I would expect the average person to understand that specifying journal files in a different sequence in their command _must necessarily_ risk changing the outcome. As long as we understand that successive `--file` switches form a List and not a Set of journal files, I don't yet see what makes this additional constraint helpful.

I see the value of clarifying the structure of a collection of journal files in another journal file; however, I would still prefer for a variety of reasons to having sibling files, not parent-child. Example:

- main
  - 2023/**/*
  - 2023 closing to retained earnings (with balance assertions)
  - 2024/**/*
  - 2024 closing to retained earnings (with balance assertions)
  - 2025/**/*

If I understand you, my balance assertions will not work when I use `--file main.journal`, is that so? I know that I can try it, but I'm interested in understanding your/hledger's intentions.

Thing 2. "Long story short: the "close to native currency case works for me"..."

The balance assertions might work, but what about the Retained Earnings amount? It should be 910.00 CAD, not 1150.00 CAD. By choosing `-V` (= `--value=end,CAD`), hledger calculates the value of the EUR and SEK revenues incorrectly. It really needs to be `--value=then,CAD`, which leads to the 240.00 CAD timing difference between Retained Earnings and Assets.

You had earlier suggested simply to convert the Revenue and Expense accounts to CAD before closing. I think this is the Accountant-approved move. My question now becomes how to do this without hardcoding foreign exchange rates in my journal, which I would very very much like to avoid. I am thinking of a kind of "publish" step when I close the 2023 books, where I can use `print` to publish a copy of my postings that have all those details spelled out, without my needing to handcraft foreign exchange rates. Before I cave through the documentation, is this possible with hledger's current features?

This was a very nice repro (which I needed, to get traction). Sorry this one "feature" cost you so much time ...

Thank you for the compliment. I'm glad that I had time to not think about it, so that I could see how to write the example a bit at a time. At least I feel like I'm a step closer to understanding how best to handle all this.

J. B. Rainsberger

unread,
Apr 27, 2025, 10:22:35 AMApr 27
to hle...@googlegroups.com
On Sat, Apr 26, 2025 at 8:58 AM Marco van Hulten <ma...@hulten.org> wrote:
[...]

The attached example works for me: main.ledger includes sub1.ledger and
sub2.ledger "side-by-side".  All of them include asserts that succeed.
I ran 'hledger -f main.ledger check -s'.

This is exactly what I did and that worked for me:

--- begin file main.FX.journal ---
include before_closing.journal
include close_retained_earnings.FX.journal
--- end ---
 
> To work around this, arrange your files in parent child relationships
> with include. Eg make one subfile include the other (it doesn't matter
> which way round).

And so, I have doubts if this is needed.  Moreover, I hope it is not
needed, because a typical use of combining multiple files has some
side-by-side inclusions (and making this a deep tree of sub-includes is
awkward).

It seems that it suffices to specify exactly only one file in the hledger command with `--file`.

Simon Michael

unread,
Apr 27, 2025, 3:16:19 PMApr 27
to hle...@googlegroups.com


On Sun, Apr 27, 2025, at 04:21, J. B. Rainsberger wrote:
On Sat, Apr 26, 2025 at 8:58 AM Marco van Hulten <ma...@hulten.org> wrote:
[...]
The attached example works for me: main.ledger includes sub1.ledger and
sub2.ledger "side-by-side".  All of them include asserts that succeed.
I ran 'hledger -f main.ledger check -s'.

This is exactly what I did and that worked for me:

--- begin file main.FX.journal ---
include before_closing.journal
include close_retained_earnings.FX.journal
--- end ---
 
> To work around this, arrange your files in parent child relationships
> with include. Eg make one subfile include the other (it doesn't matter
> which way round).

And so, I have doubts if this is needed.  Moreover, I hope it is not
needed, because a typical use of combining multiple files has some
side-by-side inclusions (and making this a deep tree of sub-includes is
awkward).

It seems that it suffices to specify exactly only one file in the hledger command with `--file`.



and pushed these tests demonstrating the current behaviour:


# sibling -f files, fails
$ hledger check assertions -f assertions1.j -f assertions2.j

# assertions1.j
2025-01-01
  (a)    1 = 1

# assertions2.j
2025-01-02
  (a)    1 = 2  ; won't see balance from previous sibling -f file


# include hierarchy, succeeds
$ hledger check assertions -f assertions11.j

# assertions11.j
2025-01-11
  (a)    11 = 11  ; first assertion
include assertions21.j
include assertions22.j
2025-03-11
  (a)    100 = 185  ; sees balance from previous children

# assertions21.j
2025-01-21
  (a)    21 = 32  ; sees balance from parent
include assertions31.j

# assertions31.j
2025-01-31
  (a)   31 = 63  ; sees balance from parent and grandparent

# assertions22.j
2025-02-22
  (a)    22 = 85  ; sees balance from parent and previous siblings/children included by parent

Simon Michael

unread,
Apr 27, 2025, 3:58:25 PMApr 27
to hle...@googlegroups.com

It seems that it suffices to specify exactly only one file in the hledger command with `--file`.

and pushed these tests demonstrating the current behaviour:

(And this makes sense, because `include` is equivalent to inlining the file (recursively). So any include hierarchy is equivalent to one big flattened file.)

The new questions are:

Should we change hledger so that the order of -f options on the command line is significant for balance assertions ?

How hard is that to implement ?

What things other than balance assertions should also become sensitive to -f order, for consistency ?

What command line options/arguments other than -f should also become order sensitive, for consistency ?

What would be the impact on existing users/data and the transition strategy ?

Simon Michael

unread,
Apr 27, 2025, 4:04:31 PMApr 27
to hle...@googlegroups.com

(And this makes sense, because `include` is equivalent to inlining the file (recursively). So any include hierarchy is equivalent to one big flattened file.)

The new questions are:

Should we change hledger so that the order of -f options on the command line is significant for balance assertions ?

How hard is that to implement ?

What things other than balance assertions should also become sensitive to -f order, for consistency ?

What command line options/arguments other than -f should also become order sensitive, for consistency ?

What would be the impact on existing users/data and the transition strategy ?


PS another consequence of making assertions see balances from a previous -f file: the second file becomes effectively dependent on the first file - it's no longer self contained. So you if you want to use FILE2 you must write -f FILE1 -f FILE2 every time.

Related:

J. B. Rainsberger

unread,
Apr 28, 2025, 8:47:14 AMApr 28
to hle...@googlegroups.com
On Sun, Apr 27, 2025 at 5:28 PM Simon Michael <si...@joyful.com> wrote:

It seems that it suffices to specify exactly only one file in the hledger command with `--file`.

and pushed these tests demonstrating the current behaviour:

(And this makes sense, because `include` is equivalent to inlining the file (recursively). So any include hierarchy is equivalent to one big flattened file.)

The new questions are:

Should we change hledger so that the order of -f options on the command line is significant for balance assertions ?

Aha! I guess I was wrong. I assumed that hledger guaranteed that it would process the files in the order in which I provide them to the command by the `--file` switch. Do I have that wrong?

If the intention is _not_ to guarantee the order of processing the files specified in the command, then I think the current constraints make sense: I think we ought to put the responsibility on the user to specify the correct processing order of the journal files by wrapping them in a container journal file. That seems clearer to me.

New question: Does the documentation scream bloody murder about no guarantee of the processing sequence of files provided with `--file`? If it doesn't, then I believe it should. And if it does, then how the hell did I miss that?!

> PS another consequence of making assertions see balances from a previous -f file: the second file becomes effectively dependent on the first file - it's no longer self contained. So if you want to use FILE2 you must write -f FILE1 -f FILE2 every time.

In practice, this doesn't bother me yet. In my example, the "close to retained earnings for year n" file is optional in the sense that the accountants want it, but I don't care for basic financial information. I don't care about Retained Earnings, since it doesn't really affect my business decisions (yet) and I would prefer to have the option to compare revenue and expenses from multiple years. This leads me to treat the `close_retained_earnings.YEAR.journal` files as optional and clearly (by their intention) dependent on the journal files from the year(s) prior. I would fully expect a journal file with that name only ever to make sense in the larger context of yearly journal files.

In theory, this might bother me, but I can't quite imagine the scenario yet. I suppose I would rely on naming files to ensure that I knew whether a journal file depends on other files or not. And if that dependency were unclear, I'd make that dependency clearer by using `include` in a container journal file.

I'm curious what others might think about that.

J. B. Rainsberger

unread,
Apr 28, 2025, 9:15:00 AMApr 28
to hle...@googlegroups.com
Since the last thread drifted to discussions of the `--file` switch, I'm continuing here with the discussion about converting balances to a base currency.

Yes, it seems like this is what I want to do. Now, the question becomes how to do it?

I have played around a little until something seemed to work, but what I have looks entirely and horrifyingly wrong. I'm hoping to learn from your suggestion without anchoring you to mine. :)

If you'd like, please use my minimal example. What posting do I need to convert the balance of Revenue to 0 CAD at the same time as posting retained earnings?

Thanks,
--
J. B. (Joe) Rainsberger :: tdd.training :: jbrains.ca ::
blog.thecodewhisperer.com

Replies from this account routinely take a few days, which allows me to reply thoughtfully. I reply more quickly to messages that clearly require answers urgently. If you need something from me and are on a deadline, then let me know how soon you need a reply so that I can better help you to get what you need. Thank you for your consideration.

Simon Michael

unread,
Apr 28, 2025, 3:27:22 PMApr 28
to hle...@googlegroups.com


On Mon, Apr 28, 2025, at 02:46, J. B. Rainsberger wrote:
Aha! I guess I was wrong. I assumed that hledger guaranteed that it would process the files in the order in which I provide them to the command by the `--file` switch. Do I have that wrong?

The file order is definitely significant for some things. More generally, we can speak of parse order. It works like this:

- Dated things (transactions, postings, balance assertions, balance assignments, P..) are not affected by parse order. Except, when multiple things have the same date, those will be processed in parse order.

- Undated directives which are position sensitive (alias, comment..) are processed in parse order.

- Undated directives which apply globally (account, commodity, payee..) are not affected by parse order.

I did a quick check for mentions of order or position sensitivity in the manual, related to CLI args or journal format:


But I guess the above general principle does not appear in the manual, perhaps it should. Or the FAQ ? It's hard to deliver the right information to the person who needs it when they need it, without overwhelming the poor user who wants other information.



> PS another consequence of making assertions see balances from a previous -f file: the second file becomes effectively dependent on the first file - it's no longer self contained. So if you want to use FILE2 you must write -f FILE1 -f FILE2 every time.

In practice, this doesn't bother me yet. In my example, the "close to retained earnings for year n" file is optional in the sense that the accountants want it, but I don't care for basic financial information. I don't care about Retained Earnings, since it doesn't really affect my business decisions (yet) and I would prefer to have the option to compare revenue and expenses from multiple years. This leads me to treat the `close_retained_earnings.YEAR.journal` files as optional and clearly (by their intention) dependent on the journal files from the year(s) prior. I would fully expect a journal file with that name only ever to make sense in the larger context of yearly journal files.

In theory, this might bother me, but I can't quite imagine the scenario yet. I suppose I would rely on naming files to ensure that I knew whether a journal file depends on other files or not. And if that dependency were unclear, I'd make that dependency clearer by using `include` in a container journal file.

I'm curious what others might think about that.
--
J. B. (Joe) Rainsberger :: tdd.training :: jbrains.ca ::

Replies from this account routinely take a few days, which allows me to reply thoughtfully. I reply more quickly to messages that clearly require answers urgently. If you need something from me and are on a deadline, then let me know how soon you need a reply so that I can better help you to get what you need. Thank you for your consideration.


--
You received this message because you are subscribed to the Google Groups "hledger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hledger+u...@googlegroups.com.

Simon Michael

unread,
Apr 28, 2025, 3:34:01 PMApr 28
to hle...@googlegroups.com
On Mon, Apr 28, 2025, at 02:46, J. B. Rainsberger wrote:
Aha! I guess I was wrong. I assumed that hledger guaranteed that it would process the files in the order in which I provide them to the command by the `--file` switch. Do I have that wrong?

New question: Does the documentation scream bloody murder about no guarantee of the processing sequence of files provided with `--file`? If it doesn't, then I believe it should. And if it does, then how the hell did I miss that?!

The file order is definitely significant for some things. More generally, we can speak of parse order (the order in which files, and lines within files, are processed). It works like this:

- Dated things (transactions, postings, balance assertions, balance assignments, P..) are not affected by parse order. Except, when multiple things have the same date, they are processed in parse order.

- Undated directives which are position sensitive (alias, comment..) are processed in parse order.

- Undated directives which are not position sensitive (account, commodity, payee..) are not affected by parse order; they apply globally.

But the general principle above doesn't appear in the manual - perhaps it should. Or the FAQ ?

(The manual is large. It's hard to deliver the right information to the person who needs it when they need it, without overwhelming the poor user with technical info they don't need.)



Simon Michael

unread,
Apr 28, 2025, 3:36:46 PMApr 28
to hle...@googlegroups.com
Excuse my double post, tricky mail UI and keyboard!

Simon Michael

unread,
Apr 28, 2025, 4:31:44 PMApr 28
to hle...@googlegroups.com


On Mon, Apr 28, 2025, at 03:14, J. B. Rainsberger wrote:
Since the last thread drifted to discussions of the `--file` switch, I'm continuing here with the discussion about converting balances to a base currency.

Yes, it seems like this is what I want to do. Now, the question becomes how to do it?

I have played around a little until something seemed to work, but what I have looks entirely and horrifyingly wrong. I'm hoping to learn from your suggestion without anchoring you to mine. :)

If you'd like, please use my minimal example. What posting do I need to convert the balance of Revenue to 0 CAD at the same time as posting retained earnings?


For people reading along - in your test repo[1], starting with zero assets, you recorded revenue in three currencies, which, valued in your base currency on the transaction dates, amounts to 910:

$ hledger -f before_closing.journal is --value=then
Income Statement 2024-12-31..2025-01-05, valued at posting date

          || 2024-12-31..2025-01-05 
==========++========================
Revenues ||                        
----------++------------------------
Revenue  ||             910.00 CAD 
----------++------------------------
          ||             910.00 CAD 
==========++========================
Expenses ||                        
----------++------------------------
----------++------------------------
          ||                      0 
==========++========================
Net:     ||             910.00 CAD 


Then after adding a hledger close --retain entry, retaining each revenue it its native currency,
you are running balancesheetequity and expecting to see a zero total indicating balanced accounting equation.

When reporting in native currencies, that is the case. But you also want to see it balanced after converting to your base currency. And doing it this way doesn't work:

$ hledger -f main.FX.journal bse --value=then
Balance Sheet With Equity 2025-04-24, valued at posting date

                          ||   2025-04-24 
==========================++==============
Assets                   ||              
--------------------------++--------------
Assets                   ||   910.00 CAD 
--------------------------++--------------
                          ||   910.00 CAD 
==========================++==============
Liabilities              ||              
--------------------------++--------------
--------------------------++--------------
                          ||            0 
==========================++==============
Equity                   ||              
--------------------------++--------------
Equity:Retained Earnings || 1,150.00 CAD 
--------------------------++--------------
                          || 1,150.00 CAD 
==========================++==============
Net:                     ||  -240.00 CAD 

We both know why, I think: Assets has several transactions which got valued with January prices, but the retained earnings transaction updating Equity didn't happen till April and got valued with April prices. (Running print or register with --value=then helps show this.)

Obligatory warning here: obviously, like most of us here I'm not an accountant, just figuring things out as I go.

These options come to mind:

A. Retain revenues/expenses on the same day each revenue/expense transaction occurs (so multiple retain transactions, not just one at the end). That way there'd be no skew in conversion rates.

B. Convert the revenues/expenses to your base currency as you record them, keeping the multi-currency complications out of your accounting system as much as possible. This is what I had in mind earlier.

If you actually do receive them in your bank account base currency, then this seems the most correct way. But if you receive them unconverted - perhaps in a brokerage or foreign bank account - it seems not correct. 

C. There's an extra transaction that needs to be entered - foreign exchange gain or loss due to changes in conversion rate occurring during a finalisation/settlement delay.

I think C probably the answer here, and would have been obvious to an accountant - a net search should find the proper term.

Questions:

- What is the actual entry for this - that hledger will accept both when reporting native currencies, and when converted to transacted value ?
- What is the easiest way to generate that entry ?

Unfortunately I'm out of brain power and time for these right now.












Simon Michael

unread,
Apr 28, 2025, 4:38:01 PMApr 28
to hle...@googlegroups.com
Well, this is the entry - but you've got to disable the 0 CAD revenue assertion:

2025-04-24 foreign exchange gain/loss
    Revenue                       -240 CAD
    Equity:FX

2025-04-24 retain earnings  ; retain:
    Revenue                       500.00 CAD ;= 0.00 CAD
    Revenue                          100 EUR = 0 EUR
    Revenue                       1,000. SEK = 0 SEK
    Equity:Retained Earnings

Then the report looks like:

$ hledger -f main.FX.journal bse --value=then 
Balance Sheet With Equity 2025-04-24, valued at posting date

                          ||   2025-04-24 
==========================++==============
Assets                   ||              
--------------------------++--------------
Assets                   ||   910.00 CAD 
--------------------------++--------------
                          ||   910.00 CAD 
==========================++==============
Liabilities              ||              
--------------------------++--------------
--------------------------++--------------
                          ||            0 
==========================++==============
Equity                   ||              
--------------------------++--------------
Equity:Retained Earnings || 1,150.00 CAD 
Equity:FX                ||  -240.00 CAD 
--------------------------++--------------
                          ||   910.00 CAD 
==========================++==============
Net:                     ||            0 

Simon Michael

unread,
Apr 28, 2025, 4:40:36 PMApr 28
to hle...@googlegroups.com
And this unbalances the bse report when showing native currencies. I don't know how/if you can show it balanced both in native and base currencies, using the same journal entries.

Simon Michael

unread,
Apr 28, 2025, 9:31:56 PMApr 28
to hle...@googlegroups.com
PS FWIW I saw a suggestion to track foreign currency assets in two ways (with two sets of records):

- in the foreign currency for accurate reconciliation
- but also, converted to the base currency ("Functional Currency") for higher-level accounting.

And: "Your foreign currency bank accounts are considered monetary assets denominated in a foreign currency. According to accounting standards (like ASC 830 in US GAAP or IAS 21 in IFRS), these monetary items must be revalued to the functional currency equivalent using the exchange rate on the balance sheet date (the last day of your accounting period)"

Which I think would look like this

2025-01-01 earn 700 SEK revenue
    revenues:sek                 -100 CAD   ; converted at today's rate, 7 SEK = 1 CAD
    assets:sek bank               100 CAD

2025-03-31 recognize foreign currency gain/loss
    assets:sek bank               -12.50 CAD = 87.50 CAD   ; now 8 SEK = 1 CAD, revalue
    revenues:sek:fx loss           12.50 CAD
    
2025-03-31 retain earnings
    revenues:sek                  100 CAD    = 0 CAD
    revenues:sek:fx loss          -12.50 CAD = 0 CAD
    equity:retained               -87.50 CAD


Simon Michael

unread,
Apr 28, 2025, 9:50:37 PMApr 28
to hle...@googlegroups.com
Just can't let it go, can you SM .... :)


; SEK journal

2025-01-01 earn 700 SEK
    revenues:sek                 -700 SEK
    assets:sek bank               700 SEK

and

; CAD journal

commodity CAD 1.00
P 2025-01-01 SEK 0.14285714 CAD
P 2025-03-31 SEK 0.125 CAD

2025-01-01 earn 700 SEK (converted at today's rate, 7 SEK = 1 CAD)
    revenues:sek                 -100 CAD
    assets:sek bank               100 CAD

2025-03-31 recognize foreign currency gain/loss (now 8 SEK = 1 CAD)
    assets:sek bank               -12.50 CAD = 87.50 CAD
    revenues:sek:fx loss           12.50 CAD
    
2025-03-31 retain earnings
    revenues:sek                  100    CAD = 0 CAD
    revenues:sek:fx loss          -12.50 CAD = 0 CAD
    equity:retained               -87.50 CAD


The above shows the accounting equation balanced when viewed in either currency.

$ hledger -f cad.journal bse -X SEK
Balance Sheet With Equity 2025-03-31, valued at period ends

                 || 2025-03-31 
=================++============
Assets          ||            
-----------------++------------
assets:sek bank ||     SEK700 
-----------------++------------
                 ||     SEK700 
=================++============
Liabilities     ||            
-----------------++------------
-----------------++------------
                 ||          0 
=================++============
Equity          ||            
-----------------++------------
equity:retained ||     SEK700 
-----------------++------------
                 ||     SEK700 
=================++============
Net:            ||          0 

$ hledger -f cad.journal bse -X CAD
Balance Sheet With Equity 2025-03-31, valued at period ends

                 || 2025-03-31 
=================++============
Assets          ||            
-----------------++------------
assets:sek bank ||  CAD 87.50 
-----------------++------------
                 ||  CAD 87.50 
=================++============
Liabilities     ||            
-----------------++------------
-----------------++------------
                 ||          0 
=================++============
Equity          ||            
-----------------++------------
equity:retained ||  CAD 87.50 
-----------------++------------
                 ||  CAD 87.50 
=================++============
Net:            ||          0 


I suspect accountants really never attempt to show multiple currencies in a single report, unlike us crazy PTA nerds.

J. B. Rainsberger

unread,
May 2, 2025, 10:30:56 AMMay 2
to hle...@googlegroups.com
On Mon, Apr 28, 2025 at 4:27 PM Simon Michael <si...@joyful.com> wrote:
 
The file order is definitely significant for some things. More generally, we can speak of parse order. It works like this:

- Dated things (transactions, postings, balance assertions, balance assignments, P..) are not affected by parse order. Except, when multiple things have the same date, those will be processed in parse order.

- Undated directives which are position sensitive (alias, comment..) are processed in parse order.

- Undated directives which apply globally (account, commodity, payee..) are not affected by parse order.

I did a quick check for mentions of order or position sensitivity in the manual, related to CLI args or journal format:


But I guess the above general principle does not appear in the manual, perhaps it should. Or the FAQ ? It's hard to deliver the right information to the person who needs it when they need it, without overwhelming the poor user who wants other information.

It seems to me that any mention of specifying multiple files in a command makes parse order relevant, and so a link to a summary (and maybe a detailed discussion) of parse order would be helpful here. By making it a separate page, you could balance the need for information with the laudable goal (which I share) of not inundating the reader with details.

Simon Michael

unread,
May 17, 2025, 4:11:37 PM (4 days ago) May 17
to hle...@googlegroups.com
I have a todo item to at least update docs on this topic (multi-file semantics, directive effects). Here are some WIP notes:

It’s useful to think about journals vs files.
A journal can consist of multiple included files. A journal is checked for errors as a unit, as if it was one big file.

You can read multiple journals at once by providing multiple -f options; but each of those is checked separately. So eg balance assertions don’t span journals.

Design issues...

setup -> create a starter journal -> what file layout ? -> directive scope -> ...

I notice that account, commodity, payee, tag directives are global in scope - no matter where they are seen, they are used to check all files in all journals (including multiple -f's)

This is usually convenient, but it also goes against the goal of having journals be standalone and not affected by transient things like the presence/absence of other journals on the command line.

It also means that if accounts change from year to year, you can't accurately check accounts in multiple year journals/files at once, even if you write the declarations down in the year files - all declarations in any file will affect all files. The only way you can be sure a year is using only the correct account names for that year is to check that file in isolation.

If alias directives and balance assertions are journal-local, why aren’t these other directives ? Seems inconsistent
Reply all
Reply to author
Forward
0 new messages