;fix: roi correctly interacts with --value (fixes #2190)
This commit is contained in:
parent
89d6f4a451
commit
08a5f1ee78
@ -110,12 +110,12 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{_rsReportOpts=ReportO
|
|||||||
e = fromEFDay end
|
e = fromEFDay end
|
||||||
cashFlowApplyCostValue = map (\(d,amt) -> (d,mixedAmountValue e d amt))
|
cashFlowApplyCostValue = map (\(d,amt) -> (d,mixedAmountValue e d amt))
|
||||||
|
|
||||||
valueBefore =
|
valueBefore = dbg3 "valueBefore" $
|
||||||
mixedAmountValue e b $
|
mixedAmountValue e b $
|
||||||
total trans (And [ investmentsQuery
|
total trans (And [ investmentsQuery
|
||||||
, Date (DateSpan Nothing (Just begin))])
|
, Date (DateSpan Nothing (Just begin))])
|
||||||
|
|
||||||
valueAfter =
|
valueAfter = dbg3 "valueAfter" $
|
||||||
mixedAmountValue e e $
|
mixedAmountValue e e $
|
||||||
total trans (And [investmentsQuery
|
total trans (And [investmentsQuery
|
||||||
, Date (DateSpan Nothing (Just end))])
|
, Date (DateSpan Nothing (Just end))])
|
||||||
@ -143,8 +143,8 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{_rsReportOpts=ReportO
|
|||||||
let smallIsZero x = if abs x < 0.01 then 0.0 else x
|
let smallIsZero x = if abs x < 0.01 then 0.0 else x
|
||||||
return [ showDate b
|
return [ showDate b
|
||||||
, showDate (addDays (-1) e)
|
, showDate (addDays (-1) e)
|
||||||
, T.pack $ showMixedAmount $ styleAmounts styles $ valueBefore
|
, T.pack $ showMixedAmountOneLineWithoutCost False $ styleAmounts styles $ valueBefore
|
||||||
, T.pack $ showMixedAmount $ styleAmounts styles $ cashFlowAmt
|
, T.pack $ showMixedAmountOneLineWithoutCost False $ styleAmounts styles $ cashFlowAmt
|
||||||
-- , T.pack $ showMixedAmount $
|
-- , T.pack $ showMixedAmount $
|
||||||
-- -- dbg0With (lbl "cashflow after styling".showMixedAmountOneLine) $
|
-- -- dbg0With (lbl "cashflow after styling".showMixedAmountOneLine) $
|
||||||
-- mapMixedAmount (amountSetFullPrecisionUpTo (Just defaultMaxPrecision)) $
|
-- mapMixedAmount (amountSetFullPrecisionUpTo (Just defaultMaxPrecision)) $
|
||||||
@ -152,8 +152,8 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{_rsReportOpts=ReportO
|
|||||||
-- -- & dbg0With (lbl "styles".show))
|
-- -- & dbg0With (lbl "styles".show))
|
||||||
-- cashFlowAmt
|
-- cashFlowAmt
|
||||||
-- -- & dbg0With (lbl "cashflow before styling".showMixedAmountOneLine)
|
-- -- & dbg0With (lbl "cashflow before styling".showMixedAmountOneLine)
|
||||||
, T.pack $ showMixedAmount $ styleAmounts styles $ valueAfter
|
, T.pack $ showMixedAmountOneLineWithoutCost False $ styleAmounts styles $ valueAfter
|
||||||
, T.pack $ showMixedAmount $ styleAmounts styles $ (valueAfter `maMinus` (valueBefore `maPlus` cashFlowAmt))
|
, T.pack $ showMixedAmountOneLineWithoutCost False $ styleAmounts styles $ (valueAfter `maMinus` (valueBefore `maPlus` cashFlowAmt))
|
||||||
, T.pack $ printf "%0.2f%%" $ smallIsZero irr
|
, T.pack $ printf "%0.2f%%" $ smallIsZero irr
|
||||||
, T.pack $ printf "%0.2f%%" $ smallIsZero periodTwr
|
, T.pack $ printf "%0.2f%%" $ smallIsZero periodTwr
|
||||||
, T.pack $ printf "%0.2f%%" $ smallIsZero annualizedTwr ]
|
, T.pack $ printf "%0.2f%%" $ smallIsZero annualizedTwr ]
|
||||||
@ -278,13 +278,13 @@ timeWeightedReturn styles showCashFlow prettyTables investmentsQuery trans mixed
|
|||||||
| val <- map showDecimal valuesOnDate
|
| val <- map showDecimal valuesOnDate
|
||||||
| oldBalance <- map showDecimal (0:unitBalances)
|
| oldBalance <- map showDecimal (0:unitBalances)
|
||||||
| balance <- map showDecimal unitBalances
|
| balance <- map showDecimal unitBalances
|
||||||
| pnl' <- map (showMixedAmount . styleAmounts styles) pnls
|
| pnl' <- map (showMixedAmountOneLineWithoutCost False . styleAmounts styles) pnls
|
||||||
| cashflow <- map (showMixedAmount . styleAmounts styles) cashflows
|
| cashflow <- map (showMixedAmountOneLineWithoutCost False . styleAmounts styles) cashflows
|
||||||
| prc <- map showDecimal unitPrices
|
| prc <- map showDecimal unitPrices
|
||||||
| udelta <- map showDecimal unitsBoughtOrSold ])
|
| udelta <- map showDecimal unitsBoughtOrSold ])
|
||||||
|
|
||||||
printf "Final unit price: %s/%s units = %s\nTotal TWR: %s%%.\nPeriod: %.2f years.\nAnnualized TWR: %.2f%%\n\n"
|
printf "Final unit price: %s/%s units = %s\nTotal TWR: %s%%.\nPeriod: %.2f years.\nAnnualized TWR: %.2f%%\n\n"
|
||||||
(showMixedAmount $ styleAmounts styles valueAfter) (showDecimal finalUnitBalance) (showDecimal finalUnitCost) (showDecimal totalTWR) years annualizedTWR
|
(showMixedAmountOneLineWithoutCost False $ styleAmounts styles valueAfter) (showDecimal finalUnitBalance) (showDecimal finalUnitCost) (showDecimal totalTWR) years annualizedTWR
|
||||||
|
|
||||||
return ((realToFrac totalTWR) :: Double, annualizedTWR)
|
return ((realToFrac totalTWR) :: Double, annualizedTWR)
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ internalRateOfReturn styles showCashFlow prettyTables (OneSpan begin end valueBe
|
|||||||
(Table
|
(Table
|
||||||
(Tab.Group Tab.NoLine (map (Header . showDate) dates))
|
(Tab.Group Tab.NoLine (map (Header . showDate) dates))
|
||||||
(Tab.Group Tab.SingleLine [Header "Amount"])
|
(Tab.Group Tab.SingleLine [Header "Amount"])
|
||||||
(map ((:[]) . T.pack . showMixedAmount . styleAmounts styles) amts))
|
(map ((:[]) . T.pack . showMixedAmountOneLineWithoutCost False . styleAmounts styles) amts))
|
||||||
|
|
||||||
-- 0% is always a solution, so require at least something here
|
-- 0% is always a solution, so require at least something here
|
||||||
case totalCF of
|
case totalCF of
|
||||||
@ -332,11 +332,11 @@ total trans query = sumPostings . filter (matchesPosting query) $ concatMap real
|
|||||||
|
|
||||||
unMix :: MixedAmount -> Quantity
|
unMix :: MixedAmount -> Quantity
|
||||||
unMix a =
|
unMix a =
|
||||||
case (unifyMixedAmount $ mixedAmountCost a) of
|
case (unifyMixedAmount a) of
|
||||||
Just a' -> aquantity a'
|
Just a' -> aquantity a'
|
||||||
Nothing -> error' $ "Amounts could not be converted to a single cost basis: " ++ show (map showAmount $ amounts a) ++
|
Nothing -> error' $ "Amounts could not be converted to a single commodity: " ++ show (map showAmount $ amounts a) ++
|
||||||
"\nConsider using --value to force all costs to be in a single commodity." ++
|
"\nConsider using --value to force all costs to be in a single commodity." ++
|
||||||
"\nFor example, \"--cost --value=end,<commodity> --infer-market-prices\", where commodity is the one that was used to pay for the investment."
|
"\nFor example, \"--value=end,<commodity> --infer-market-prices\", where commodity is the one that was used for investment valuations."
|
||||||
|
|
||||||
-- Show Decimal rounded to two decimal places, unless it has less places already. This ensures that "2" won't be shown as "2.00"
|
-- Show Decimal rounded to two decimal places, unless it has less places already. This ensures that "2" won't be shown as "2.00"
|
||||||
showDecimal :: Decimal -> String
|
showDecimal :: Decimal -> String
|
||||||
|
|||||||
@ -228,14 +228,18 @@ $ hledger -f- roi -p 2019-11
|
|||||||
Investment 10 B
|
Investment 10 B
|
||||||
|
|
||||||
2019/11/02 Example
|
2019/11/02 Example
|
||||||
Investment -10 B @@ 100 A
|
Assets:Checking -100 C
|
||||||
|
Investment 100 C
|
||||||
|
|
||||||
|
2019/11/02 Example
|
||||||
|
Investment -9 B @@ 100 A
|
||||||
Assets:Checking 101 A
|
Assets:Checking 101 A
|
||||||
Unrealized PnL
|
Unrealized PnL
|
||||||
$ hledger -f- roi -p 2019-11 --inv Investment --pnl PnL
|
$ hledger -f- roi -p 2019-11 --inv Investment --pnl PnL
|
||||||
>2
|
>2
|
||||||
hledger: Error: Amounts could not be converted to a single cost basis: ["10 B","-10 B @@ 100 A"]
|
hledger: Error: Amounts could not be converted to a single commodity: ["10 B","-9 B @@ 100 A","100 C"]
|
||||||
Consider using --value to force all costs to be in a single commodity.
|
Consider using --value to force all costs to be in a single commodity.
|
||||||
For example, "--cost --value=end,<commodity> --infer-market-prices", where commodity is the one that was used to pay for the investment.
|
For example, "--value=end,<commodity> --infer-market-prices", where commodity is the one that was used for investment valuations.
|
||||||
>= 1
|
>= 1
|
||||||
|
|
||||||
# ** 10. Forcing valuation via --value
|
# ** 10. Forcing valuation via --value
|
||||||
@ -362,3 +366,24 @@ $ hledger -f - roi --inv stocks --pnl expenses --value=then,€ -Y
|
|||||||
+---++------------+------------++---------------+----------+-------------+------++---------++------------+----------+
|
+---++------------+------------++---------------+----------+-------------+------++---------++------------+----------+
|
||||||
|
|
||||||
>= 0
|
>= 0
|
||||||
|
|
||||||
|
# ** 15. Correctly work with --value and complex valuation chains
|
||||||
|
<
|
||||||
|
P 2023-01-01 B 20A
|
||||||
|
P 2023-01-01 C 1B
|
||||||
|
|
||||||
|
2023-01-01
|
||||||
|
investment 1C @@ 20A
|
||||||
|
investment 4B @@ 80A
|
||||||
|
assets
|
||||||
|
|
||||||
|
P 2023-12-31 C 2B
|
||||||
|
|
||||||
|
$ hledger -f - roi --inv investment --pnl income --value='end,B' -b2023 -e2024
|
||||||
|
+---++------------+------------++---------------+----------+-------------+-----++--------++------------+----------+
|
||||||
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR || TWR/period | TWR/year |
|
||||||
|
+===++============+============++===============+==========+=============+=====++========++============+==========+
|
||||||
|
| 1 || 2023-01-01 | 2023-12-31 || 0 | 5B | 6B | 1B || 20.00% || 20.00% | 20.00% |
|
||||||
|
+---++------------+------------++---------------+----------+-------------+-----++--------++------------+----------+
|
||||||
|
|
||||||
|
>= 0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user