Unable to get individual stockr roi/xirr in 1.99.4 lots syntax

79 views
Skip to first unread message

alind sharma

unread,
Sep 12, 2026, 8:49:42 AMSep 12
to hledger
First of all, congrats for 1.99.4. Hopeful to get 2.0 soon.

I was trying to use lots syntax but suffered some bottlenecks.

1. Bonus issue : When stocks give bonus, I can add add it simply by adding a 0 cost. But when the same 0 cost bonus stock goes to split, I cannot take negate x quantity  and add 2x quantity with half the price. As the price is 0 so its half. And hledger is reducing it and thinking that it is a transfer from one account to another. I have to divide the transfer as two transactions on the same date for it to be accepted.

2. How to keep the dividend associated with the individual stocks and still consider it to be part of roi/xirr calculations. As I am getting that amount from that particular stock.

3. How to get roi/xirr for individual stock. Previous to lots, i was using assets:investments:stocks:AAPL syntax to get it. But in lots syntax that info is gone from account name so I can't filter it in roi command. 

Note: INR, INRM, and symbol ₹ are for Indian currency rupee.

My example file is follows :

; Declare top level accounts, setting their types and display order;
; Replace these account names with yours; it helps commands like bs and is detect them.
account assets       ; type:A, things I own
account liabilities  ; type:L, things I owe
account equity       ; type:E, net worth or "total investment"; equal to A - L
account revenues     ; type:R, inflow categories; part of E, separated for reporting
account expenses     ; type:X, outflow categories; part of E, separated for reporting
account revenues:capital_gains    ; type:G

; Declare commodities/currencies and their decimal mark, digit grouping,
; number of decimal places..
commodity 9,99,99,999.00 ₹
commodity INR 9,99,99,999.00
commodity 999,999,999.00 INRM
commodity 999999999.00 INRC
D 9,99,99,999.00 ₹

commodity LTTS; lots:
commodity INFY; lots:

; import the prices
P 2020/01/01 "INRM"  1.00
P 2020/01/01 "INRC"  1.00


P 2023/03/31 INFY  100.00
P 2023/03/31 LTTS  200.00


; Ledger
2022-04-01 indial deposit
    assets:cash:zerodha                      -1000.00 ₹
    revenues:misc
 
2022-04-06 buy ltts  ; stocks:buy
    assets:investments:stocks      10 LTTS @@ 200.00 ₹
    expenses:zerodha:brokerage                  5.00 ₹
    assets:cash:zerodha                      -205.00 ₹

2022-05-06 buy ltts  ; stocks:buy
    assets:investments:stocks      10 LTTS @@ 220.00 ₹
    expenses:zerodha:brokerage                  5.00 ₹
    assets:cash:zerodha                      -225.00 ₹

2022-06-06 bonus ltts  ; stocks:bonus
    assets:investments:stocks      20 LTTS @@ 0.00 ₹
    equity:bonus-shares           -20 LTTS @@ 0.00 ₹

2022-07-06 split ltts  ; stocks:split
    assets:investments:stocks     -10 LTTS {2022-04-06} @@ 200.00 ₹
    assets:investments:stocks      20 LTTS {2022-04-06} @@ 200.00 ₹
    assets:investments:stocks     -10 LTTS {2022-05-06} @@ 220.00 ₹
    assets:investments:stocks      20 LTTS {2022-05-06} @@ 220.00 ₹

2022-07-06 split ltts  ; stocks:split
    assets:investments:stocks     -20 LTTS {2022-06-06}  @@ 0
    equity:split-share
     
2022-07-06 split ltts  ; stocks:split
    assets:investments:stocks      40 LTTS {2022-06-06}  @@ 0
    equity:split-share

2022-04-07 buy infy  ; stocks:buy
    assets:investments:stocks      10 INFY @@ 20.00 ₹
    expenses:zerodha:brokerage                  1.00 ₹
    assets:cash:zerodha                       -21.00 ₹

2023-01-16 sell ltts  ; stocks:sell
    assets:investments:stocks        -5 LTTS @@ 150.00 ₹
    expenses:zerodha:brokerage                   10.00 ₹  ; selling brokerage
    assets:cash:zerodha                         140.00 ₹
;    revenues:capital_gains                      -50.00 ₹

2023-02-16 sell ltts  ; stocks:sell
    assets:investments:stocks        -2 LTTS @@ 60.00 ₹
    expenses:zerodha:brokerage                  10.00 ₹  ; selling brokerage
    assets:cash:zerodha                         50.00 ₹
;    revenues:capital_gains                      -50.00 ₹
;
2022-05-23 dividend ltts  ; stocks:dividend
    assets:cash:airtel_bank                      5.00 ₹
    revenues:dividend:ltts                      


ledger_2022_23.journal

alind sharma

unread,
Sep 12, 2026, 10:40:36 AMSep 12
to hledger
Attached better formatted one.
ledger_2022_23.journal

Simon Michael

unread,
Sep 12, 2026, 11:26:33 AMSep 12
to hle...@googlegroups.com
Hi Alind,

That's a nice example ! 

For Q3, try --lots or --pivot=cur:acct

I will investigate the rest.

alind sharma

unread,
Sep 12, 2026, 4:06:00 PMSep 12
to hledger
Thanks Simon for answering the question.

It is giving me xirr values of individual stocks if i follow these commands (Hope I am following correctly. This is my first time using pivot flag)

For stock INFY:
./hledger -f ledger_2022_23.journal --lots --pivot=cur:acct roi --inv INFY:assets:investments:stocks --pnl 'revenues:capital_gains|equity:unrealised-gain' -V 

for stock LTTS:
./hledger -f ledger_2022_23.journal --lots --pivot=cur:acct roi --inv INFY:assets:investments:stocks --pnl 'revenues:capital_gains|equity:unrealised-gain' -V 

Pivot is converting like this (./hledger -f ledger_2022_23.journal --lots --pivot=cur:acct  print):

2022-05-23 dividend ltts  ; stocks:dividend
    ₹:assets:cash:airtel_bank                      5.00 ₹
    ₹:revenues:dividend:ltts                      -5.00 ₹

 
2022-06-06 bonus ltts  ; stocks:bonus
    LTTS:assets:investments:stocks:{2022-06-06, "0001", 0}   20 LTTS @@ 0.00 ₹
    LTTS:equity:bonus-shares                                -20 LTTS @@ 0.00 ₹
 
2022-07-06 split 2:1 ltts  ; stocks:split
    LTTS:assets:investments:stocks:{2022-04-06, "0001", 20.00 ₹}  -10 LTTS {2022-04-06} @@ 200.00 ₹
    LTTS:assets:investments:stocks:{2022-04-06, "0001", 10.00 ₹}   20 LTTS {2022-04-06} @@ 200.00 ₹
    LTTS:assets:investments:stocks:{2022-05-06, "0001", 22.00 ₹}  -10 LTTS {2022-05-06} @@ 220.00 ₹
    LTTS:assets:investments:stocks:{2022-05-06, "0001", 11.00 ₹}   20 LTTS {2022-05-06} @@ 220.00 ₹

 
2022-07-06 split ltts  ; stocks:split
    LTTS:assets:investments:stocks:{2022-06-06, "0001", 0}  -20 LTTS {2022-06-06} @@ 0.00 ₹
    ₹:equity:split-share
 

Simon Michael

unread,
Sep 12, 2026, 4:21:52 PMSep 12
to alind sharma, hle...@googlegroups.com
Ah, I assumed you were using the holdings reports. Try this also:

hledger holdings --lots --pivot=cur:acct INFY

(or omit INFY to show them all at once).

roi and holdings may not appear to agree in all aspects. There are some related notes in https://github.com/hledgerorg/hledger/blob/main/examples/lots/irr.journal (you may have seen it).

--pivot=cur:acct is saying "prepend postings' commodity symbol to the account name".  I suggested it as a hack to help with grouping and filtering by commodity in a multicommodity holdings report, there are probably other ways to do it.
--
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,
Sep 12, 2026, 4:34:12 PMSep 12
to hle...@googlegroups.com, alind sharma
Ah, the holdings report calculates XIRR up to today by default. Adjusting "today" to right after the last P record makes it agree exactly with the roi report.

$ hledger -f alind.journal print cur:INFY
2022-04-07 buy infy  ; stocks:buy
    assets:investments:stocks                     10 INFY @@ 20.00 ₹
    expenses:zerodha:brokerage                     1.00 ₹
    assets:cash:zerodha                          -21.00 ₹

$ hledger -f alind.journal prices cur:INFY
P 2023-03-31 INFY 100.00 ₹

$ hledger -f alind.journal --lots --pivot=cur:acct roi --inv INFY:assets:investments:stocks --pnl 'revenues:capital_gains|equity:unrealised-gain' -V
+---++------------+------------++---------------+----------+-------------+----------++----------++------------+----------+
|   ||      Begin |        End || Value (begin) | Cashflow | Value (end) |      PnL ||      IRR || TWR/period | TWR/year |
+===++============+============++===============+==========+=============+==========++==========++============+==========+
| 1 || 2022-04-07 | 2023-03-31 ||             0 |  20.00 ₹ |  1,000.00 ₹ | 980.00 ₹ || 5252.40% ||      0.00% |    0.00% |
+---++------------+------------++---------------+----------+-------------+----------++----------++------------+----------+

$ hledger -f alind.journal --lots --pivot=cur:acct holdings INFY
Holdings on 2026-09-12

                                                     ||       Date   Age    Units  Unit cost     Price     Cost       Value  Weight     UGain   UGain%  RGain    XIRR 
=====================================================++===============================================================================================================
INFY:assets:investments:stocks:{2022-04-07, 2.00 ₹} || 2022-04-07  4.4y  10 INFY     2.00 ₹  100.00 ₹  20.00 ₹  1,000.00 ₹  100.0%  980.00 ₹  4900.0%         141.7% 
-----------------------------------------------------++---------------------------------------------------------------------------------------------------------------
                                                     ||                                                 20.00 ₹  1,000.00 ₹  100.0%  980.00 ₹  4900.0%         141.7% 
~/src/hledger/examples/lots$ hledger -f alind.journal --lots --pivot=cur:acct holdings INFY --today 2023-04-01
Holdings on 2023-04-01

                                                     ||       Date   Age    Units  Unit cost     Price     Cost       Value  Weight     UGain   UGain%  RGain     XIRR 
=====================================================++================================================================================================================
INFY:assets:investments:stocks:{2022-04-07, 2.00 ₹} || 2022-04-07  359d  10 INFY     2.00 ₹  100.00 ₹  20.00 ₹  1,000.00 ₹  100.0%  980.00 ₹  4900.0%         5252.4% 
-----------------------------------------------------++----------------------------------------------------------------------------------------------------------------
                                                     ||                                                 20.00 ₹  1,000.00 ₹  100.0%  980.00 ₹  4900.0%         5252.4% 

Simon Michael

unread,
Sep 12, 2026, 4:47:53 PMSep 12
to hle...@googlegroups.com
PS that roi report can be written more simply:

hledger -f alind.journal roi -V --pivot cur:acct --inv INFY:assets:investments:stocks

I'm not sure what end date roi uses for its calculations - latest posting or P date, perhaps.

Simon Michael

unread,
Sep 12, 2026, 8:01:26 PMSep 12
to hledger
Hi Alind,

based on your example (thanks!), I have committed some fixes in the main branch. In particular, 

- Splitting all those lots in one transaction now works as expected.

- The numeric lot labels added automatically to distinguish same-basis-date lots, are no longer reused. (So in your stock split, they change from "0001" to "0002".)

- Zero cost basis acquisitions (bonus shares) now preserve the base currency symbol, and show Value/Weight/UGain as expected.



Now the holdings report, showing lot detail, looks like:

$ hledger -f examples/lots/alind.journal holdings --lots -e 2023-04-02 
Holdings on 2023-04-01

                                                         ||       Date   Age    Units  Unit cost     Price      Cost        Value  Weight        UGain   UGain%     RGain     XIRR 
=========================================================++========================================================================================================================
 assets:investments:stocks:{2022-04-06, "0002", 10.00 ₹} || 2022-04-06  360d  13 LTTS    10.00 ₹  200.00 ₹  130.00 ₹   2,600.00 ₹   16.7%   2,470.00 ₹  1900.0%  140.00 ₹  3876.1% 
 assets:investments:stocks:{2022-04-07, 2.00 ₹}          || 2022-04-07  359d  10 INFY     2.00 ₹  100.00 ₹   20.00 ₹   1,000.00 ₹    6.4%     980.00 ₹  4900.0%            5252.4% 
 assets:investments:stocks:{2022-05-06, "0002", 11.00 ₹} || 2022-05-06  330d  20 LTTS    11.00 ₹  200.00 ₹  220.00 ₹   4,000.00 ₹   25.6%   3,780.00 ₹  1718.2%            5032.7% 
 assets:investments:stocks:{2022-06-06, "0002", 0.00 ₹}  || 2022-06-06  299d  40 LTTS          0  200.00 ₹         0   8,000.00 ₹   51.3%   8,000.00 ₹                             
---------------------------------------------------------++------------------------------------------------------------------------------------------------------------------------
                                                         ||                                                 370.00 ₹  15,600.00 ₹  100.0%  15,230.00 ₹  4116.2%  140.00 ₹  4342.1% 

The pivot cur:acct trick isn't really needed, I just wanted a way to group the lots by commodity. Eg I got this from playing around:

$ hledger -f examples/lots/alind.journal holdings --lots --pivot=cur:acct -e 2023-04-02 -t --drop 4
Holdings on 2023-04-01

                               ||       Date   Age    Units  Unit cost     Price      Cost        Value  Weight        UGain   UGain%     RGain     XIRR 
===============================++========================================================================================================================
 {2022-04-07, 2.00 ₹}          || 2022-04-07  359d  10 INFY     2.00 ₹  100.00 ₹   20.00 ₹   1,000.00 ₹    6.4%     980.00 ₹  4900.0%            5252.4% 
 {2022-04-06, "0002", 10.00 ₹} || 2022-04-06  360d  13 LTTS    10.00 ₹  200.00 ₹  130.00 ₹   2,600.00 ₹   16.7%   2,470.00 ₹  1900.0%  140.00 ₹  3876.1% 
 {2022-05-06, "0002", 11.00 ₹} || 2022-05-06  330d  20 LTTS    11.00 ₹  200.00 ₹  220.00 ₹   4,000.00 ₹   25.6%   3,780.00 ₹  1718.2%            5032.7% 
 {2022-06-06, "0002", 0.00 ₹}  || 2022-06-06  299d  40 LTTS          0  200.00 ₹         0   8,000.00 ₹   51.3%   8,000.00 ₹                             
-------------------------------++------------------------------------------------------------------------------------------------------------------------
                               ||                                                 370.00 ₹  15,600.00 ₹  100.0%  15,230.00 ₹  4116.2%  140.00 ₹  4342.1% 


These and other improvements in main will be released in 1.99.5 in a couple of weeks I hope. For now: the Install page tells how to build hledger main, or if it helps there'll be a linux binary soon at  https://github.com/hledgerorg/hledger/actions/runs/34726804028 .


Re how to associate dividends with their stocks for calculating roi/xirr - I'll answer that separately.

Simon Michael

unread,
Sep 12, 2026, 8:18:52 PMSep 12
to hledger

3. How to get roi/xirr for individual stock. Previous to lots, i was using assets:investments:stocks:AAPL syntax to get it. But in lots syntax that info is gone from account name so I can't filter it in roi command. 

`holdings` calculates XIRR from lot flows only, so it can't currently include dividends. That might need looking into.

For `roi`, I'll share these AI answers - if you can confirm, I'll mention these in the manual.

Method 1 — route the dividend through the investment account (classic roi idiom: the investment produced income, which was immediately withdrawn):

2022-05-23 dividend
    revenues:dividend:ltts             -5.00 ₹
    assets:investments:stocks:ltts      5.00 ₹
    assets:investments:stocks:ltts     -5.00 ₹
    assets:cash:airtel_bank             5.00 ₹

The ₹ postings in a lot-tracked account are harmless — ₹ isn't lotful, so the lot machinery ignores them, and the journal loads cleanly.


Method 2 — keep per-ticker parent accounts. With assets:investments:stocks:ltts, lots nest underneath (...:ltts:{2022-04-06, ...}). That gives --inv a clean per-stock handle (the cur:LTTS alternative can't work here, because the dividend postings are in ₹). This also re-answers Q3; the holdings report groups nicely by ticker with this account scheme.

Then per-stock roi including dividends:

hledger roi --inv assets:investments:stocks:ltts --pnl 'revenues:dividend:ltts|revenues:gain|equity:unrealised-gain' --value=end,₹ --infer-market-prices

(gain accounts in --pnl per the manual's "Using roi with lots" section). Verified against the variant journal: the 5 ₹ moves from contributed cashflow (4,350 → 4,345) into PnL (10,250 → 10,255), IRR rises 321.95% → 322.55%, and TWR gains a valuation window at the dividend date.


Simon Michael

unread,
Sep 12, 2026, 8:36:00 PMSep 12
to hledger
For `roi`, I'll share these AI answers - if you can confirm, I'll mention these in the manual.

Method 1

PS actually those might be both needed, not alternative methods.

alind sharma

unread,
Sep 13, 2026, 4:13:46 PMSep 13
to hledger
Thanks for helping me out Simon. 
I will try the other examples and confirm for xirr/split/bonus etc.
The dividend's solution looks too much to be included in otherwise a wonderful journal. Dividends are quite frequent so to add those many entries seems extra work. 
It would be ok if only 1st solution (equity +/- one )is required.
I will see if i can find some other workaround for the same.
Is there a link from where I can download the latest binary for experimentation.
Reply all
Reply to author
Forward
0 new messages