roi: use MixedAmount more and keep styles when reporting commodities
This commit is contained in:
parent
14a3b9833c
commit
07a9f11962
@ -49,10 +49,10 @@ roimode = hledgerCommandMode
|
|||||||
data OneSpan = OneSpan
|
data OneSpan = OneSpan
|
||||||
Day -- start date, inclusive
|
Day -- start date, inclusive
|
||||||
Day -- end date, exclusive
|
Day -- end date, exclusive
|
||||||
Quantity -- value of investment at the beginning of day on spanBegin_
|
MixedAmount -- value of investment at the beginning of day on spanBegin_
|
||||||
Quantity -- value of investment at the end of day on spanEnd_
|
MixedAmount -- value of investment at the end of day on spanEnd_
|
||||||
[(Day,Quantity)] -- all deposits and withdrawals (but not changes of value) in the DateSpan [spanBegin_,spanEnd_)
|
[(Day,MixedAmount)] -- all deposits and withdrawals (but not changes of value) in the DateSpan [spanBegin_,spanEnd_)
|
||||||
[(Day,Quantity)] -- all PnL changes of the value of investment in the DateSpan [spanBegin_,spanEnd_)
|
[(Day,MixedAmount)] -- all PnL changes of the value of investment in the DateSpan [spanBegin_,spanEnd_)
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
|
||||||
@ -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 $ showDecimal valueBefore
|
, T.pack $ showMixedAmount valueBefore
|
||||||
, T.pack $ showDecimal cashFlowAmt
|
, T.pack $ showMixedAmount cashFlowAmt
|
||||||
, T.pack $ showDecimal valueAfter
|
, T.pack $ showMixedAmount valueAfter
|
||||||
, T.pack $ showDecimal (valueAfter - (valueBefore + cashFlowAmt))
|
, T.pack $ showMixedAmount (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 ]
|
||||||
|
|
||||||
@ -148,8 +148,9 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{rsOpts=ReportOpts{..}
|
|||||||
|
|
||||||
TL.putStrLn $ Ascii.render prettyTables id id id table
|
TL.putStrLn $ Ascii.render prettyTables id id id table
|
||||||
|
|
||||||
timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spanBegin spanEnd valueBefore valueAfter cashFlow pnl) = do
|
timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spanBegin spanEnd valueBeforeAmt valueAfter cashFlow pnl) = do
|
||||||
let initialUnitPrice = 100
|
let valueBefore = unMix valueBeforeAmt
|
||||||
|
let initialUnitPrice = 100 :: Decimal
|
||||||
let initialUnits = valueBefore / initialUnitPrice
|
let initialUnits = valueBefore / initialUnitPrice
|
||||||
let changes =
|
let changes =
|
||||||
-- If cash flow and PnL changes happen on the same day, this
|
-- If cash flow and PnL changes happen on the same day, this
|
||||||
@ -170,16 +171,16 @@ timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spa
|
|||||||
tail $
|
tail $
|
||||||
scanl
|
scanl
|
||||||
(\(_, _, unitPrice, unitBalance) (date, amt) ->
|
(\(_, _, unitPrice, unitBalance) (date, amt) ->
|
||||||
let valueOnDate = total trans (And [investmentsQuery, Date (DateSpan Nothing (Just date))])
|
let valueOnDate = unMix $ total trans (And [investmentsQuery, Date (DateSpan Nothing (Just date))])
|
||||||
in
|
in
|
||||||
case amt of
|
case amt of
|
||||||
Right amt ->
|
Right amt ->
|
||||||
-- we are buying or selling
|
-- we are buying or selling
|
||||||
let unitsBoughtOrSold = amt / unitPrice
|
let unitsBoughtOrSold = unMix amt / unitPrice
|
||||||
in (valueOnDate, unitsBoughtOrSold, unitPrice, unitBalance + unitsBoughtOrSold)
|
in (valueOnDate, unitsBoughtOrSold, unitPrice, unitBalance + unitsBoughtOrSold)
|
||||||
Left pnl ->
|
Left pnl ->
|
||||||
-- PnL change
|
-- PnL change
|
||||||
let valueAfterDate = valueOnDate + pnl
|
let valueAfterDate = valueOnDate + unMix pnl
|
||||||
unitPrice' = valueAfterDate/unitBalance
|
unitPrice' = valueAfterDate/unitBalance
|
||||||
in (valueOnDate, 0, unitPrice', unitBalance))
|
in (valueOnDate, 0, unitPrice', unitBalance))
|
||||||
(0, 0, initialUnitPrice, initialUnits)
|
(0, 0, initialUnitPrice, initialUnits)
|
||||||
@ -187,7 +188,7 @@ timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spa
|
|||||||
|
|
||||||
let finalUnitBalance = if null units then initialUnits else let (_,_,_,u) = last units in u
|
let finalUnitBalance = if null units then initialUnits else let (_,_,_,u) = last units in u
|
||||||
finalUnitPrice = if finalUnitBalance == 0 then initialUnitPrice
|
finalUnitPrice = if finalUnitBalance == 0 then initialUnitPrice
|
||||||
else valueAfter / finalUnitBalance
|
else (unMix valueAfter) / finalUnitBalance
|
||||||
-- Technically, totalTWR should be (100*(finalUnitPrice - initialUnitPrice) / initialUnitPrice), but initalUnitPrice is 100, so 100/100 == 1
|
-- Technically, totalTWR should be (100*(finalUnitPrice - initialUnitPrice) / initialUnitPrice), but initalUnitPrice is 100, so 100/100 == 1
|
||||||
totalTWR = roundTo 2 $ (finalUnitPrice - initialUnitPrice)
|
totalTWR = roundTo 2 $ (finalUnitPrice - initialUnitPrice)
|
||||||
years = fromIntegral (diffDays spanEnd spanBegin) / 365 :: Double
|
years = fromIntegral (diffDays spanEnd spanBegin) / 365 :: Double
|
||||||
@ -201,7 +202,7 @@ timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spa
|
|||||||
(valuesOnDate',unitsBoughtOrSold', unitPrices', unitBalances') = unzip4 units
|
(valuesOnDate',unitsBoughtOrSold', unitPrices', unitBalances') = unzip4 units
|
||||||
add x lst = if valueBefore/=0 then x:lst else lst
|
add x lst = if valueBefore/=0 then x:lst else lst
|
||||||
dates = add spanBegin dates'
|
dates = add spanBegin dates'
|
||||||
cashflows = add valueBefore cashflows'
|
cashflows = add valueBeforeAmt cashflows'
|
||||||
pnls = add 0 pnls'
|
pnls = add 0 pnls'
|
||||||
unitsBoughtOrSold = add initialUnits unitsBoughtOrSold'
|
unitsBoughtOrSold = add initialUnits unitsBoughtOrSold'
|
||||||
unitPrices = add initialUnitPrice unitPrices'
|
unitPrices = add initialUnitPrice unitPrices'
|
||||||
@ -218,13 +219,13 @@ timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spa
|
|||||||
| value <- map showDecimal valuesOnDate
|
| value <- map showDecimal valuesOnDate
|
||||||
| oldBalance <- map showDecimal (0:unitBalances)
|
| oldBalance <- map showDecimal (0:unitBalances)
|
||||||
| balance <- map showDecimal unitBalances
|
| balance <- map showDecimal unitBalances
|
||||||
| pnl <- map showDecimal pnls
|
| pnl <- map showMixedAmount pnls
|
||||||
| cashflow <- map showDecimal cashflows
|
| cashflow <- map showMixedAmount 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"
|
||||||
(showDecimal valueAfter) (showDecimal finalUnitBalance) (showDecimal finalUnitPrice) (showDecimal totalTWR) years annualizedTWR
|
(showMixedAmount valueAfter) (showDecimal finalUnitBalance) (showDecimal finalUnitPrice) (showDecimal totalTWR) years annualizedTWR
|
||||||
|
|
||||||
return annualizedTWR
|
return annualizedTWR
|
||||||
|
|
||||||
@ -242,7 +243,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 . showDecimal) amounts))
|
(map ((:[]) . T.pack . showMixedAmount) 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
|
||||||
@ -256,11 +257,11 @@ internalRateOfReturn showCashFlow prettyTables (OneSpan spanBegin spanEnd valueB
|
|||||||
SearchFailed -> error' $ "Error (SearchFailed): Failed to find solution for Internal Rate of Return (IRR).\n"
|
SearchFailed -> error' $ "Error (SearchFailed): Failed to find solution for Internal Rate of Return (IRR).\n"
|
||||||
++ " Either search does not converge to a solution, or converges too slowly."
|
++ " Either search does not converge to a solution, or converges too slowly."
|
||||||
|
|
||||||
type CashFlow = [(Day, Quantity)]
|
type CashFlow = [(Day, MixedAmount)]
|
||||||
|
|
||||||
interestSum :: Day -> CashFlow -> Double -> Double
|
interestSum :: Day -> CashFlow -> Double -> Double
|
||||||
interestSum referenceDay cf rate = sum $ map go cf
|
interestSum referenceDay cf rate = sum $ map go cf
|
||||||
where go (t,m) = fromRational (toRational m) * (rate ** (fromIntegral (referenceDay `diffDays` t) / 365))
|
where go (t,m) = fromRational (toRational (unMix m)) * (rate ** (fromIntegral (referenceDay `diffDays` t) / 365))
|
||||||
|
|
||||||
|
|
||||||
calculateCashFlow :: [Transaction] -> Query -> CashFlow
|
calculateCashFlow :: [Transaction] -> Query -> CashFlow
|
||||||
@ -268,8 +269,8 @@ calculateCashFlow trans query = filter ((/=0).snd) $ map go trans
|
|||||||
where
|
where
|
||||||
go t = (transactionDate2 t, total [t] query)
|
go t = (transactionDate2 t, total [t] query)
|
||||||
|
|
||||||
total :: [Transaction] -> Query -> Quantity
|
total :: [Transaction] -> Query -> MixedAmount
|
||||||
total trans query = unMix $ sumPostings $ filter (matchesPosting query) $ concatMap realPostings trans
|
total trans query = sumPostings $ filter (matchesPosting query) $ concatMap realPostings trans
|
||||||
|
|
||||||
unMix :: MixedAmount -> Quantity
|
unMix :: MixedAmount -> Quantity
|
||||||
unMix a =
|
unMix a =
|
||||||
|
|||||||
@ -12,7 +12,7 @@ hledger -f- roi --inv investment --pnl pnl -b 2017 -e 2018 -Y
|
|||||||
+---++------------+------------++---------------+----------+-------------+-----++-------+-------+
|
+---++------------+------------++---------------+----------+-------------+-----++-------+-------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
+===++============+============++===============+==========+=============+=====++=======+=======+
|
+===++============+============++===============+==========+=============+=====++=======+=======+
|
||||||
| 1 || 2017-01-01 | 2017-12-31 || 0 | 200 | 200 | 0 || 0.00% | 0.00% |
|
| 1 || 2017-01-01 | 2017-12-31 || 0 | $200 | $200 | 0 || 0.00% | 0.00% |
|
||||||
+---++------------+------------++---------------+----------+-------------+-----++-------+-------+
|
+---++------------+------------++---------------+----------+-------------+-----++-------+-------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
@ -31,7 +31,7 @@ hledger -f- roi --inv investment --pnl pnl -b 2017 -e 2018 -Y
|
|||||||
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
+===++============+============++===============+==========+=============+=====++========+========+
|
+===++============+============++===============+==========+=============+=====++========+========+
|
||||||
| 1 || 2017-01-01 | 2017-12-31 || 0 | 100 | 112 | 12 || 12.00% | 12.00% |
|
| 1 || 2017-01-01 | 2017-12-31 || 0 | $100 | $112 | $12 || 12.00% | 12.00% |
|
||||||
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
@ -95,7 +95,7 @@ hledger -f- roi --inv investment --pnl pnl -b 2017 -e 2018 -Y
|
|||||||
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
+===++============+============++===============+==========+=============+=====++========+========+
|
+===++============+============++===============+==========+=============+=====++========+========+
|
||||||
| 1 || 2017-01-01 | 2017-12-31 || 0 | 100 | 112 | 12 || 12.00% | 12.00% |
|
| 1 || 2017-01-01 | 2017-12-31 || 0 | $100 | $112 | $12 || 12.00% | 12.00% |
|
||||||
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
@ -118,7 +118,7 @@ hledger -f- roi --inv investment --pnl pnl -b 2017 -e 2018 -Y
|
|||||||
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
+===++============+============++===============+==========+=============+=====++========+========+
|
+===++============+============++===============+==========+=============+=====++========+========+
|
||||||
| 1 || 2017-01-01 | 2017-12-31 || 0 | 200 | 220 | 20 || 12.72% | 10.00% |
|
| 1 || 2017-01-01 | 2017-12-31 || 0 | $200 | $220 | $20 || 12.72% | 10.00% |
|
||||||
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
+---++------------+------------++---------------+----------+-------------+-----++--------+--------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
@ -138,11 +138,11 @@ hledger -f- roi --inv investment --pnl pnl -b 2017 -e 2018 -Y
|
|||||||
investment = $20
|
investment = $20
|
||||||
pnl
|
pnl
|
||||||
>>>
|
>>>
|
||||||
+---++------------+------------++---------------+----------+-------------+------++---------+---------+
|
+---++------------+------------++---------------+----------+-------------+-------++---------+---------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
+===++============+============++===============+==========+=============+======++=========+=========+
|
+===++============+============++===============+==========+=============+=======++=========+=========+
|
||||||
| 1 || 2017-01-01 | 2017-12-31 || 0 | 200 | 20 | -180 || -95.73% | -90.00% |
|
| 1 || 2017-01-01 | 2017-12-31 || 0 | $200 | $20 | $-180 || -95.73% | -90.00% |
|
||||||
+---++------------+------------++---------------+----------+-------------+------++---------+---------+
|
+---++------------+------------++---------------+----------+-------------+-------++---------+---------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
|
|
||||||
@ -172,10 +172,10 @@ hledger -f- roi --inv investment --pnl pnl -b 2017 -e 2018 -Q
|
|||||||
+---++------------+------------++---------------+----------+-------------+-----++---------+---------+
|
+---++------------+------------++---------------+----------+-------------+-----++---------+---------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
+===++============+============++===============+==========+=============+=====++=========+=========+
|
+===++============+============++===============+==========+=============+=====++=========+=========+
|
||||||
| 1 || 2017-01-01 | 2017-03-31 || 0 | 100 | 100 | 0 || 0.00% | 0.00% |
|
| 1 || 2017-01-01 | 2017-03-31 || 0 | $100 | $100 | 0 || 0.00% | 0.00% |
|
||||||
| 2 || 2017-04-01 | 2017-06-30 || 100 | 0 | 110 | 10 || 46.56% | 46.56% |
|
| 2 || 2017-04-01 | 2017-06-30 || $100 | 0 | $110 | $10 || 46.56% | 46.56% |
|
||||||
| 3 || 2017-07-01 | 2017-09-30 || 110 | 100 | 210 | 0 || 0.00% | 0.00% |
|
| 3 || 2017-07-01 | 2017-09-30 || $110 | $100 | $210 | 0 || 0.00% | 0.00% |
|
||||||
| 4 || 2017-10-01 | 2017-12-31 || 210 | -50 | 155 | -5 || -11.83% | -11.82% |
|
| 4 || 2017-10-01 | 2017-12-31 || $210 | $-50 | $155 | $-5 || -11.83% | -11.82% |
|
||||||
+---++------------+------------++---------------+----------+-------------+-----++---------+---------+
|
+---++------------+------------++---------------+----------+-------------+-----++---------+---------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
@ -206,7 +206,7 @@ hledger -f- roi --inv investment --pnl pnl -b 2017-06 -e 2018
|
|||||||
+---++------------+------------++---------------+----------+-------------+-----++-------+--------+
|
+---++------------+------------++---------------+----------+-------------+-----++-------+--------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
+===++============+============++===============+==========+=============+=====++=======+========+
|
+===++============+============++===============+==========+=============+=====++=======+========+
|
||||||
| 1 || 2017-06-01 | 2017-12-31 || 100 | 50 | 155 | 5 || 5.24% | 11.45% |
|
| 1 || 2017-06-01 | 2017-12-31 || $100 | $50 | $155 | $5 || 5.24% | 11.45% |
|
||||||
+---++------------+------------++---------------+----------+-------------+-----++-------+--------+
|
+---++------------+------------++---------------+----------+-------------+-----++-------+--------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
@ -258,7 +258,7 @@ hledger -f- roi -p 2019-11 --inv Investment --pnl PnL --value cost,A --infer-val
|
|||||||
+---++------------+------------++---------------+----------+-------------+-----++----------+-------+
|
+---++------------+------------++---------------+----------+-------------+-----++----------+-------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
||||||
+===++============+============++===============+==========+=============+=====++==========+=======+
|
+===++============+============++===============+==========+=============+=====++==========+=======+
|
||||||
| 1 || 2019-11-01 | 2019-11-30 || 0 | -1 | 0 | 1 || 3678.34% | 0.00% |
|
| 1 || 2019-11-01 | 2019-11-30 || 0 | -1 A | 0 | 1 A || 3678.34% | 0.00% |
|
||||||
+---++------------+------------++---------------+----------+-------------+-----++----------+-------+
|
+---++------------+------------++---------------+----------+-------------+-----++----------+-------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
@ -277,10 +277,10 @@ P 2021-01-01 $ 73.88
|
|||||||
assets:investment =11000
|
assets:investment =11000
|
||||||
income:investment
|
income:investment
|
||||||
>>>
|
>>>
|
||||||
+---++------------+------------++---------------+----------+-------------+-------++---------+---------+
|
+---++------------+------------++---------------+----------+-------------+-----++---------+---------+
|
||||||
| || Begin | End || Value (begin) | Cashflow | Value (end) | PnL || IRR | TWR |
|
| || 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% |
|
| 1 || 2020-12-02 | 2021-01-02 || 0 | $135 | $149 | $14 || 196.58% | 196.58% |
|
||||||
+---++------------+------------++---------------+----------+-------------+-------++---------+---------+
|
+---++------------+------------++---------------+----------+-------------+-----++---------+---------+
|
||||||
|
|
||||||
>>>=0
|
>>>=0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user