roi: honor all kinds of --value switches

This commit is contained in:
Dmitry Astapov 2021-02-09 22:40:56 +00:00 committed by Simon Michael
parent f4d81377af
commit 8013d650f3
2 changed files with 39 additions and 11 deletions

View File

@ -19,7 +19,6 @@ import Data.Time.Calendar
import Text.Printf import Text.Printf
import Data.Function (on) import Data.Function (on)
import Data.List import Data.List
import Data.Maybe (fromMaybe)
import Numeric.RootFinding import Numeric.RootFinding
import Data.Decimal import Data.Decimal
import qualified Data.Text as T import qualified Data.Text as T
@ -61,8 +60,10 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{rsOpts=ReportOpts{..}
d <- getCurrentDay d <- getCurrentDay
-- We may be converting posting amounts to value, per hledger_options.m4.md "Effect of --value on reports". -- We may be converting posting amounts to value, per hledger_options.m4.md "Effect of --value on reports".
let let
tvalue = transactionApplyCostValuation (journalPriceOracle infer_value_ j) (journalCommodityStyles j) periodlast (rsToday rspec) cost_ value_ priceOracle = (journalPriceOracle infer_value_ j)
where periodlast = fromMaybe (rsToday rspec) $ reportPeriodOrJournalLastDay rspec j styles = (journalCommodityStyles j)
today = rsToday rspec
mixedAmountValue periodlast date = mixedAmountApplyCostValuation priceOracle styles periodlast today date cost_ value_
let let
ropts = rsOpts rspec ropts = rsOpts rspec
showCashFlow = boolopt "cashflow" rawopts showCashFlow = boolopt "cashflow" rawopts
@ -75,7 +76,7 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{rsOpts=ReportOpts{..}
pnlQuery <- makeQuery "pnl" pnlQuery <- makeQuery "pnl"
let let
trans = dbg3 "investments" $ map tvalue $ jtxns $ filterJournalTransactions investmentsQuery j trans = dbg3 "investments" $ jtxns $ filterJournalTransactions investmentsQuery j
journalSpan = journalSpan =
let dates = map transactionDate2 trans in let dates = map transactionDate2 trans in
@ -93,26 +94,31 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{rsOpts=ReportOpts{..}
let spans = case requestedInterval of let spans = case requestedInterval of
NoInterval -> [wholeSpan] NoInterval -> [wholeSpan]
interval -> interval ->
splitSpan interval $ splitSpan interval wholeSpan
spanIntersect journalSpan wholeSpan
tableBody <- forM spans $ \(DateSpan (Just spanBegin) (Just spanEnd)) -> do tableBody <- forM spans $ \(DateSpan (Just spanBegin) (Just spanEnd)) -> do
-- Spans are [spanBegin,spanEnd), and spanEnd is 1 day after then actual end date we are interested in -- Spans are [spanBegin,spanEnd), and spanEnd is 1 day after then actual end date we are interested in
let let
cashFlowApplyCostValue = map (\(d,amt) -> (d,mixedAmountValue spanEnd d amt))
valueBefore = valueBefore =
mixedAmountValue spanEnd spanBegin $
total trans (And [ investmentsQuery total trans (And [ investmentsQuery
, Date (DateSpan Nothing (Just spanBegin))]) , Date (DateSpan Nothing (Just spanBegin))])
valueAfter = valueAfter =
mixedAmountValue spanEnd spanEnd $
total trans (And [investmentsQuery total trans (And [investmentsQuery
, Date (DateSpan Nothing (Just spanEnd))]) , Date (DateSpan Nothing (Just spanEnd))])
cashFlow = cashFlow =
cashFlowApplyCostValue $
calculateCashFlow trans (And [ Not investmentsQuery calculateCashFlow trans (And [ Not investmentsQuery
, Not pnlQuery , Not pnlQuery
, Date (DateSpan (Just spanBegin) (Just spanEnd)) ] ) , Date (DateSpan (Just spanBegin) (Just spanEnd)) ] )
pnl = pnl =
cashFlowApplyCostValue $
calculateCashFlow trans (And [ Not investmentsQuery calculateCashFlow trans (And [ Not investmentsQuery
, pnlQuery , pnlQuery
, Date (DateSpan (Just spanBegin) (Just spanEnd)) ] ) , Date (DateSpan (Just spanBegin) (Just spanEnd)) ] )
@ -121,7 +127,7 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{rsOpts=ReportOpts{..}
OneSpan spanBegin spanEnd valueBefore valueAfter cashFlow pnl OneSpan spanBegin spanEnd valueBefore valueAfter cashFlow pnl
irr <- internalRateOfReturn showCashFlow prettyTables thisSpan irr <- internalRateOfReturn showCashFlow prettyTables thisSpan
twr <- timeWeightedReturn showCashFlow prettyTables investmentsQuery trans thisSpan twr <- timeWeightedReturn showCashFlow prettyTables investmentsQuery trans mixedAmountValue thisSpan
let cashFlowAmt = negate $ sum $ map snd cashFlow let cashFlowAmt = negate $ sum $ map snd cashFlow
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
@ -143,7 +149,7 @@ 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 valueBeforeAmt valueAfter cashFlow pnl) = do timeWeightedReturn showCashFlow prettyTables investmentsQuery trans mixedAmountValue (OneSpan spanBegin spanEnd valueBeforeAmt valueAfter cashFlow pnl) = do
let valueBefore = unMix valueBeforeAmt let valueBefore = unMix valueBeforeAmt
let initialUnitPrice = 100 :: Decimal let initialUnitPrice = 100 :: Decimal
let initialUnits = valueBefore / initialUnitPrice let initialUnits = valueBefore / initialUnitPrice
@ -166,7 +172,7 @@ timeWeightedReturn showCashFlow prettyTables investmentsQuery trans (OneSpan spa
tail $ tail $
scanl scanl
(\(_, _, unitPrice, unitBalance) (date, amt) -> (\(_, _, unitPrice, unitBalance) (date, amt) ->
let valueOnDate = unMix $ total trans (And [investmentsQuery, Date (DateSpan Nothing (Just date))]) let valueOnDate = unMix $ mixedAmountValue spanEnd date $ total trans (And [investmentsQuery, Date (DateSpan Nothing (Just date))])
in in
case amt of case amt of
Right amt -> Right amt ->

View File

@ -263,8 +263,30 @@ hledger -f- roi -p 2019-11 --inv Investment --pnl PnL --cost --value=then,A --in
>>>=0 >>>=0
# 11. Dont use crazy amount of decimal places # 11. Use "then" prices. 10000/76.20 = 131.23, 11000/73.88=148.89
hledger -f - roi --inv assets:investment --pnl income:investment -X '$' hledger -f - roi --inv assets:investment --pnl income:investment --value=then,'$'
<<<
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 | $131 | $149 | $18 || 321.99% | 321.81% |
+---++------------+------------++---------------+----------+-------------+-----++---------+---------+
>>>=0
# 12. Use "end" prices. 10000/73.88=135.35
hledger -f - roi --inv assets:investment --pnl income:investment --value=end,'$'
<<< <<<
P 2020-12-01 $ 76.20 P 2020-12-01 $ 76.20
P 2021-01-01 $ 73.88 P 2021-01-01 $ 73.88