roi: fix insane precision bug, discovered in #1417
This commit is contained in:
parent
db3fe16645
commit
14a3b9833c
@ -131,10 +131,10 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{rsOpts=ReportOpts{..}
|
|||||||
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 spanBegin
|
return [ showDate spanBegin
|
||||||
, showDate (addDays (-1) spanEnd)
|
, showDate (addDays (-1) spanEnd)
|
||||||
, T.pack $ show valueBefore
|
, T.pack $ showDecimal valueBefore
|
||||||
, T.pack $ show cashFlowAmt
|
, T.pack $ showDecimal cashFlowAmt
|
||||||
, T.pack $ show valueAfter
|
, T.pack $ showDecimal valueAfter
|
||||||
, T.pack $ show (valueAfter - (valueBefore + cashFlowAmt))
|
, T.pack $ showDecimal (valueAfter - (valueBefore + cashFlowAmt))
|
||||||
, T.pack $ printf "%0.2f%%" $ smallIsZero irr
|
, T.pack $ printf "%0.2f%%" $ smallIsZero irr
|
||||||
, T.pack $ printf "%0.2f%%" $ smallIsZero twr ]
|
, T.pack $ printf "%0.2f%%" $ smallIsZero twr ]
|
||||||
|
|
||||||
@ -193,7 +193,6 @@ timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spa
|
|||||||
years = fromIntegral (diffDays spanEnd spanBegin) / 365 :: Double
|
years = fromIntegral (diffDays spanEnd spanBegin) / 365 :: Double
|
||||||
annualizedTWR = 100*((1+(realToFrac totalTWR/100))**(1/years)-1) :: Double
|
annualizedTWR = 100*((1+(realToFrac totalTWR/100))**(1/years)-1) :: Double
|
||||||
|
|
||||||
let s d = show $ roundTo 2 d
|
|
||||||
when showCashFlow $ do
|
when showCashFlow $ do
|
||||||
printf "\nTWR cash flow for %s - %s\n" (showDate spanBegin) (showDate (addDays (-1) spanEnd))
|
printf "\nTWR cash flow for %s - %s\n" (showDate spanBegin) (showDate (addDays (-1) spanEnd))
|
||||||
let (dates', amounts) = unzip changes
|
let (dates', amounts) = unzip changes
|
||||||
@ -216,19 +215,19 @@ timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spa
|
|||||||
, Tbl.Group SingleLine [Header "Pnl", Header "Cashflow", Header "Unit price", Header "Units"]
|
, Tbl.Group SingleLine [Header "Pnl", Header "Cashflow", Header "Unit price", Header "Units"]
|
||||||
, Tbl.Group SingleLine [Header "New Unit Balance"]])
|
, Tbl.Group SingleLine [Header "New Unit Balance"]])
|
||||||
[ [value, oldBalance, pnl, cashflow, prc, udelta, balance]
|
[ [value, oldBalance, pnl, cashflow, prc, udelta, balance]
|
||||||
| value <- map s valuesOnDate
|
| value <- map showDecimal valuesOnDate
|
||||||
| oldBalance <- map s (0:unitBalances)
|
| oldBalance <- map showDecimal (0:unitBalances)
|
||||||
| balance <- map s unitBalances
|
| balance <- map showDecimal unitBalances
|
||||||
| pnl <- map s pnls
|
| pnl <- map showDecimal pnls
|
||||||
| cashflow <- map s cashflows
|
| cashflow <- map showDecimal cashflows
|
||||||
| prc <- map s unitPrices
|
| prc <- map showDecimal unitPrices
|
||||||
| udelta <- map s unitsBoughtOrSold ])
|
| udelta <- map showDecimal unitsBoughtOrSold ])
|
||||||
|
|
||||||
printf "Final unit price: %s/%s units = %s\nTotal TWR: %s%%.\nPeriod: %.2f years.\nAnnualized TWR: %.2f%%\n\n" (s valueAfter) (s finalUnitBalance) (s finalUnitPrice) (s totalTWR) years annualizedTWR
|
printf "Final unit price: %s/%s units = %s\nTotal TWR: %s%%.\nPeriod: %.2f years.\nAnnualized TWR: %.2f%%\n\n"
|
||||||
|
(showDecimal valueAfter) (showDecimal finalUnitBalance) (showDecimal finalUnitPrice) (showDecimal totalTWR) years annualizedTWR
|
||||||
|
|
||||||
return annualizedTWR
|
return annualizedTWR
|
||||||
|
|
||||||
|
|
||||||
internalRateOfReturn showCashFlow prettyTables (OneSpan spanBegin spanEnd valueBefore valueAfter cashFlow _pnl) = do
|
internalRateOfReturn showCashFlow prettyTables (OneSpan spanBegin spanEnd valueBefore valueAfter cashFlow _pnl) = do
|
||||||
let prefix = (spanBegin, negate valueBefore)
|
let prefix = (spanBegin, negate valueBefore)
|
||||||
|
|
||||||
@ -243,7 +242,7 @@ internalRateOfReturn showCashFlow prettyTables (OneSpan spanBegin spanEnd valueB
|
|||||||
(Table
|
(Table
|
||||||
(Tbl.Group NoLine (map (Header . showDate) dates))
|
(Tbl.Group NoLine (map (Header . showDate) dates))
|
||||||
(Tbl.Group SingleLine [Header "Amount"])
|
(Tbl.Group SingleLine [Header "Amount"])
|
||||||
(map ((:[]) . T.pack . show) amounts))
|
(map ((:[]) . T.pack . showDecimal) amounts))
|
||||||
|
|
||||||
-- 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
|
||||||
@ -279,3 +278,11 @@ unMix 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 cost basis: " ++ 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, \"--value cost,<commodity> --infer-value\", where commodity is the one that was used to pay for the investment."
|
"\nFor example, \"--value cost,<commodity> --infer-value\", where commodity is the one that was used to pay for the investment."
|
||||||
|
|
||||||
|
-- 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 d = if d == rounded then show d else show rounded
|
||||||
|
where
|
||||||
|
rounded = roundTo 2 d
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -262,3 +262,25 @@ hledger -f- roi -p 2019-11 --inv Investment --pnl PnL --value cost,A --infer-val
|
|||||||
+---++------------+------------++---------------+----------+-------------+-----++----------+-------+
|
+---++------------+------------++---------------+----------+-------------+-----++----------+-------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
|
|
||||||
|
# 11. Dont use crazy amount of decimal places
|
||||||
|
hledger -f - roi --inv assets:investment --pnl income:investment -X '$'
|
||||||
|
<<<
|
||||||
|
P 2020-12-01 $ 76.20
|
||||||
|
P 2021-01-01 $ 73.88
|
||||||
|
|
||||||
|
2020-12-02 invest
|
||||||
|
assets:investment 10000
|
||||||
|
assets
|
||||||
|
|
||||||
|
2021-01-02 get profit
|
||||||
|
assets:investment =11000
|
||||||
|
income:investment
|
||||||
|
>>>
|
||||||
|
+---++------------+------------++---------------+----------+-------------+-------++---------+---------+
|
||||||
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
|
+===++============+============++===============+==========+=============+=======++=========+=========+
|
||||||
|
| 1 || 2020-12-02 | 2021-01-02 || 0 | 135.35 | 148.89 | 13.54 || 196.58% | 196.58% |
|
||||||
|
+---++------------+------------++---------------+----------+-------------+-------++---------+---------+
|
||||||
|
|
||||||
|
>>>=0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user