Opening and closing balances when tracking a house value

Hi!

I have been using hledger to track our personal expenses and things have been great so far. It has been slight over a year and I am still learning so much about accounting and the possibilities with hledger.

As we move into 2026, I tried closing out 2025 and starting with a fresh file for 2026. Something I have not been able to comprehend has to do with tracking my house value in my journal.

For example, lets say that this is my 2025 journal:

2025-01-01 Opening                               ; Bought a house years ago
    assets:house     1000000 USD @@ 800000 USD   ; Bought for 800k, now worth 1m
    equity:opening

2025-06-30 Value update
    assets:house    =1100000 USD                 ; house value went up again
    equity:unrealizedgains

Things are looking good at the end of the year:

hledger -f example.journal bs
Balance Sheet 2025-06-30

              ||  2025-06-30 
==============++=============
 Assets       ||             
--------------++-------------
 assets:house || 1100000 USD 
--------------++-------------
              || 1100000 USD 
==============++=============
 Liabilities  ||             
--------------++-------------
--------------++-------------
              ||           0 
==============++=============
 Net:         || 1100000 USD

Now it’s time to close 2025 and move this into 2026:

hledger -f example.journal close --open --show-costs >example-2026-open.journal
cat example-2026-open.journal                                        
2026-01-08 opening balances  ; clopen:
    assets:house                                      100000 USD
    assets:house                       1000000 USD @@ 800000 USD = 1100000 USD
    equity:opening/closing balances

My first surprise is that I now have 2 different assets/accounts for the house. Reading the documentation I think this might have to do with lots but I am unsure. I would have expected one line/account which would have stated I have an assets of 1,1m which has an acquisition cost of 800k…

Looking at the situation from 2026, I see this:

hledger -f example-2026-open.journal bs
Balance Sheet 2026-01-08

              ||  2026-01-08 
==============++=============
 Assets       ||             
--------------++-------------
 assets:house || 1100000 USD 
--------------++-------------
              || 1100000 USD 
==============++=============
 Liabilities  ||             
--------------++-------------
--------------++-------------
              ||           0 
==============++=============
 Net:         || 1100000 USD

Which is what I expect, but, if I look at the gains, I see:

hledger -f example-2026-open.journal bs --gain
Balance Sheet 2026-01-08 (Historical Gain), valued at period ends

              || 2026-01-08 
==============++============
 Assets       ||            
--------------++------------
 assets:house || 200000 USD 
--------------++------------
              || 200000 USD 
==============++============
 Liabilities  ||            
--------------++------------
--------------++------------
              ||          0 
==============++============
 Net:         || 200000 USD 

The gain is “only” 200k, not the 300k I would have expected (1,1m value - 800k acquisition cost). What am I doing wrong?

My first surprise is that I now have 2 different assets/accounts for the house.

It's because of the different costs:

    assets:house     1000000 USD @@ 800000 USD   ; Bought for 800k, now worth 1m

posts 1000000 USD with a total cost of 800000, and

    assets:house    =1100000 USD                 ; house value went up again

posts 100000 USD with no cost.
These amounts are handled almost like two separate commodities.
Reports that don't show costs will show them summed together,
but close --show-costs shows them separately.

The gain is “only” 200k, not the 300k I would have expected

I'm not sure what the explanation is for this yet. I haven't used the --gain report much.

And, I'm not sure that journal entry makes sense;
I have not seen the same commodity used on both sides of @ or @@ before.

I usually see it done like this:

2025-01-01 Opening
    assets:house     1 HOUSE @@ 800000 USD   ; Bought this house years ago for 800k
    equity:opening

; Value updates
P 2025-01-01 HOUSE 1000000 USD
P 2025-06-30 HOUSE 1100000 USD

Then bs -B shows the cost, bs -V [-e DATE] shows the value on DATE,
and bs --gain [-e DATE] shows the gain/loss as of DATE.

Thank you for the quick reply!

This was insightful!!

You are of course right,. and then you also said:

Which lead me to further play around and that produced and even stranger result (notice the 06-30 statement which includes both value and cost - albeit using the same currency on both side of the @@):

% cat example2.journal

2025-01-01 Opening                              ; Bought a house years ago
    assets:house    1000000 USD @@ 800000 USD   ; Bought for 800k, now worth 1m
    equity:opening

2025-06-30 Value update
    assets:house  =1100000 USD @@ 800000 USD    ; house value went up again
    equity:unrealizedgains

% hledger -f example2.journal bs --gain
Balance Sheet 2025-06-30 (Historical Gain), valued at period ends

              || 2025-06-30 
==============++============
 Assets       ||            
--------------++------------
 assets:house || 500000 USD 
--------------++------------
              || 500000 USD 
==============++============
 Liabilities  ||            
--------------++------------
--------------++------------
              ||          0 
==============++============
 Net:         || 500000 USD

Which is too many an even stranger number… likely a bug somewhere, or perhaps a statement which should be rejected?

I then tried your proposed approach:

2025-01-01 Opening     ; Bought a house years ago
    assets:house       1 HOUSE @@ 800000 USD   ; Bought for 800k, now worth 1m
    equity:opening

P 2025-01-01 HOUSE 1000000 USD

P 2025-06-30 HOUSE 1100000 USD      ; House value went up

P 2025-09-30 HOUSE  900000 USD      ; And house value went down

And this appears to work with my use cases.

My unsolicited opinion is that USD @@ USD should be treated like an error and rejected.

So many weird implications otherwise.. For example, if you try to –Infer-market-prices from this and then –value the balances in USD, should they be inflated/discounted because of this transaction? :slight_smile:

3 Likes

I'm inclined to agree, it's fun to imagine what meaning we could find for it but nothing useful immediately comes to mind. Not that it has been causing much trouble to date.

1 Like