valuation: more thorough --value-at; document status (#329, #999)

This feature turns out to be quite involved, as valuation interacts
with the many report variations. Various bugs/specs have been
fixed/clarified relating to register's running total, balance totals
etc. Eg register's total should now be the sum of the posting amount
values, not the values of the original sums. Current level of support
has been documented.

When valuing at transaction date, we once again do early valuation of
all posting amounts, to get more correct results. variants. This means
--value-at=t can be slower than other valuation modes when there are
many transactions and many prices. This could be revisited for
optimisation when things are more settled.
This commit is contained in:
Simon Michael 2019-05-03 12:24:02 -07:00
parent 7dd5475187
commit ebf5ed93f2
11 changed files with 314 additions and 200 deletions

View File

@ -1010,7 +1010,7 @@ journalAmounts = getConst . traverseJournalAmounts (Const . (:[]))
overJournalAmounts :: (Amount -> Amount) -> Journal -> Journal
overJournalAmounts f = runIdentity . traverseJournalAmounts (Identity . f)
-- | Traverses over all ofthe amounts in the journal, in the order
-- | Traverses over all of the amounts in the journal, in the order
-- indicated by 'journalAmounts'.
traverseJournalAmounts
:: Applicative f

View File

@ -180,33 +180,38 @@ brNegate (is, tot) = (map brItemNegate is, -tot)
-- or a specified date.
brValue :: ReportOpts -> Journal -> BalanceReport -> BalanceReport
brValue ropts@ReportOpts{..} j (items, total) =
([ (n, n', i, mixedAmountValue prices d a) | (n,n',i,a) <- items ]
,mixedAmountValue prices d total
([ (n, n', i, val a) | (n,n',i,a) <- items ]
,val total
)
where
val amt =
let val' d = mixedAmountValue prices d amt in
case value_at_ of
AtTransaction -> amt -- this case is converted earlier, see Balance.hs
AtPeriod ->
let mperiodorjournallastday = mperiodlastday <|> journalEndDate False j
-- Get the last day of the report period.
-- Will be Nothing if no report period is specified, or also
-- if ReportOpts does not have today_ set, since we need that
-- to get the report period robustly.
mperiodlastday :: Maybe Day = do
t <- today_
let q = queryFromOpts t ropts
qend <- queryEndDate False q
return $ addDays (-1) qend
d = fromMaybe (error' "brValue: expected a non-empty journal") -- XXX shouldn't happen
mperiodorjournallastday
in val' d
AtNow -> case today_ of
Just d -> val' d
Nothing -> error' "brValue: ReportOpts today_ is unset so could not satisfy --value-at=now"
AtDate d -> val' d
-- prices are in parse order - sort into date then parse order,
-- & reversed for quick lookup of the latest price.
prices = reverse $ sortOn mpdate $ jmarketprices j
d = case value_at_ of
AtTransaction -> error' "sorry, --value-at=transaction is not yet supported with balance reports" -- XXX
AtPeriod -> fromMaybe (error' "brValue: expected a non-empty journal") mperiodorjournallastday -- XXX shouldn't happen
AtNow -> case today_ of
Just d -> d
Nothing -> error' "brValue: ReportOpts today_ is unset so could not satisfy --value-at=now"
AtDate d -> d
-- Get the last day of the report period.
-- Will be Nothing if no report period is specified, or also
-- if ReportOpts does not have today_ set, since we need that
-- to get the report period robustly.
mperiodlastday :: Maybe Day = do
t <- today_
let q = queryFromOpts t ropts
qend <- queryEndDate False q
return $ addDays (-1) qend
mperiodorjournallastday = mperiodlastday <|> journalEndDate False j
-- -- | Find the best commodity to convert to when asked to show the
-- -- market value of this commodity on the given date. That is, the one
-- -- in which it has most recently been market-priced, ie the commodity

View File

@ -291,15 +291,18 @@ mbrValue ReportOpts{..} Journal{..} (MultiBalanceReport (spans, rows, (coltotals
,val end rowavgtotal)
)
where
ends = map (fromMaybe (error' "mbrValue: expected all report periods to have an end date") . spanEnd) spans -- XXX shouldn't happen
ends = map (addDays (-1) . fromMaybe (error' "mbrValue: expected all report periods to have an end date") . spanEnd) spans -- XXX shouldn't happen
end = lastDef (error' "mbrValue: expected at least one report subperiod") ends -- XXX shouldn't happen
val periodend amt = mixedAmountValue prices d amt
val periodend amt = mixedAmountValue prices valuationdate amt
where
-- prices are in parse order - sort into date then parse order,
-- & reversed for quick lookup of the latest price.
prices = reverse $ sortOn mpdate jmarketprices
d = case value_at_ of
AtTransaction -> error' "sorry, --value-at=transaction is not yet supported with balance reports" -- XXX
valuationdate = case value_at_ of
AtTransaction ->
error' "sorry, --value-at=transaction with balance reports is not yet supported"
AtPeriod | average_ || row_total_ ->
error' "sorry, --value-at=period with -T or -A in periodic balance reports is not yet supported"
AtPeriod -> periodend
AtNow -> case today_ of
Just d -> d

View File

@ -90,8 +90,16 @@ postingsReport opts q j =
startbal | average_ opts = if historical then precedingavg else 0
| otherwise = if historical then precedingsum else 0
startnum = if historical then length precedingps + 1 else 1
runningcalc | average_ opts = \i avg amt -> avg + divideMixedAmount (fromIntegral i) (amt - avg) -- running average
| otherwise = \_ bal amt -> bal + amt -- running total
runningcalc = registerRunningCalculationFn opts
-- | Based on the given report options, return a function that does the appropriate
-- running calculation for the register report, ie a running average or running total.
-- This function will take the item number, previous average/total, and new posting amount,
-- and return the new average/total.
registerRunningCalculationFn :: ReportOpts -> (Int -> MixedAmount -> MixedAmount -> MixedAmount)
registerRunningCalculationFn ropts
| average_ ropts = \i avg amt -> avg + divideMixedAmount (fromIntegral i) (amt - avg)
| otherwise = \_ bal amt -> bal + amt
totallabel = "Total"
@ -240,23 +248,45 @@ negatePostingAmount p = p { pamount = negate $ pamount p }
-- or the posting dates if journal is empty - shouldn't happen),
-- or today's date (gives an error if today_ is not set in ReportOpts),
-- or a specified date.
--
-- Special case: when --value-at=transaction is combined with a report interval,
-- assume amounts were converted to value earlier and do nothing here.
--
prValue :: ReportOpts -> Journal -> PostingsReport -> PostingsReport
prValue ropts@ReportOpts{..} j@Journal{..} (totallabel, items) = (totallabel, items')
where
items' = [ (md, md2, desc, p{pamount=val $ pamount p}, val tot)
| (md, md2, desc, p, tot) <- items
, let val = mixedAmountValue prices (valuationdate $ postingDate p)
-- convert postings amounts to value
items' = [ (md, md2, desc, p', t') | (md, md2, desc, p, t) <- items
, let pdate = postingDate p
, let pamt' = val pdate (pamount p)
, let p' = p{pamount = pamt'}
, let t' = val pdate t -- In some cases, revaluing the totals/averages is fine.
-- With --value-at=t, we revalue postings early instead.
-- XXX --value=at=m -M is still a problem
]
valuationdate pdate =
case value_at_ of
AtTransaction | interval_ /= NoInterval -> error' "sorry, --value-at=transaction is not yet supported with periodic register reports" -- XXX
AtPeriod | interval_ /= NoInterval -> error' "sorry, --value-at=transaction is not yet supported with periodic register reports" -- XXX
AtTransaction -> pdate
AtPeriod -> fromMaybe pdate mperiodorjournallastday
AtNow -> case today_ of
Just d -> d
Nothing -> error' "prValue: ReportOpts today_ is unset so could not satisfy --value-at=now"
AtDate d -> d
val pdate amt =
let val' d = mixedAmountValue prices d amt in
case (value_at_, interval_) of
(AtTransaction, _) -> amt -- in this case we revalued postings early (Register.hs)
(AtPeriod, NoInterval) -> val' $ fromMaybe pdate mperiodorjournallastday
(AtPeriod, _) ->
error' "sorry, --value-at=period with periodic register reports is not yet supported"
-- XXX need to calculate total from period-valued postings
-- -- Get the last day of this subperiod. We can't always get it from the report item
-- -- (only the first items in each period have the period start/end dates).
-- -- The following kludge seems to work.. XXX
-- let subperiodlastday =
-- addDays (-1) $
-- fromMaybe (error' "prValue: expected a date here") $ -- should not happen
-- spanEnd $
-- headDef (error' "prValue: expected at least one span here") $ -- should not happen, splitting a well-formed span
-- splitSpan i (DateSpan (Just pdate) Nothing)
-- in val' subperiodlastday
(AtNow, _) -> case today_ of
Just d -> val' d
Nothing -> error' "prValue: ReportOpts today_ is unset so could not satisfy --value-at=now"
(AtDate d, _) -> val' d
where
mperiodorjournallastday = mperiodlastday <|> journalEndDate False j
-- Get the last day of the report period.

View File

@ -82,7 +82,7 @@ data ValueDate =
| AtPeriod -- ^ Calculate values as of each report period's last day
| AtNow -- ^ Calculate values as of today (report generation date)
| AtDate Day -- ^ Calculate values as of some other date
deriving (Show,Data) -- Eq,Typeable
deriving (Show,Data,Eq) -- Typeable
instance Default ValueDate where def = AtNow
@ -99,8 +99,8 @@ data ReportOpts = ReportOpts {
,interval_ :: Interval
,statuses_ :: [Status] -- ^ Zero, one, or two statuses to be matched
,cost_ :: Bool
,value_ :: Bool
,value_at_ :: ValueDate
,value_ :: Bool -- ^ Should amounts be converted to market value
,value_at_ :: ValueDate -- ^ Which valuation date should be used for market value
,depth_ :: Maybe Int
,display_ :: Maybe DisplayExp -- XXX unused ?
,date2_ :: Bool
@ -109,8 +109,9 @@ data ReportOpts = ReportOpts {
,real_ :: Bool
,format_ :: Maybe FormatStr
,query_ :: String -- all arguments, as a string
-- register command only
--
,average_ :: Bool
-- register command only
,related_ :: Bool
-- balance-type commands only
,balancetype_ :: BalanceType

View File

@ -234,6 +234,7 @@ Currently, empty cells show 0.
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NamedFieldPuns #-}
@ -300,14 +301,14 @@ balancemode = hledgerCommandMode
-- | The balance command, prints a balance report.
balance :: CliOpts -> Journal -> IO ()
balance opts@CliOpts{rawopts_=rawopts,reportopts_=ropts} j = do
balance opts@CliOpts{rawopts_=rawopts,reportopts_=ropts@ReportOpts{..}} j = do
d <- getCurrentDay
case lineFormatFromOpts ropts of
Left err -> error' $ unlines [err]
Right _ -> do
let format = outputFormatFromOpts opts
budget = boolopt "budget" rawopts
interval = interval_ ropts
interval = interval_
case (budget, interval) of
(True, _) -> do
@ -324,13 +325,16 @@ balance opts@CliOpts{rawopts_=rawopts,reportopts_=ropts} j = do
(False, NoInterval) -> do
-- single column balance report
-- With --value-at=transaction, convert all amounts to value before summing them.
let j' | value_at_ == AtTransaction = journalValueAtTransactionDate ropts j
| otherwise = j
let report
| balancetype_ ropts `elem` [HistoricalBalance, CumulativeChange]
| balancetype_ `elem` [HistoricalBalance, CumulativeChange]
= let ropts' | flat_ ropts = ropts
| otherwise = ropts{accountlistmode_=ALTree}
in balanceReportFromMultiBalanceReport ropts' (queryFromOpts d ropts) j
in balanceReportFromMultiBalanceReport ropts' (queryFromOpts d ropts) j'
-- for historical balances we must use balanceReportFromMultiBalanceReport (also forces --no-elide)
| otherwise = balanceReport ropts (queryFromOpts d ropts) j -- simple Ledger-style balance report
| otherwise = balanceReport ropts (queryFromOpts d ropts) j' -- simple Ledger-style balance report
render = case format of
"csv" -> \ropts r -> (++ "\n") $ printCSV $ balanceReportAsCsv ropts r
"html" -> \_ _ -> error' "Sorry, HTML output is not yet implemented for this kind of report." -- TODO
@ -339,7 +343,13 @@ balance opts@CliOpts{rawopts_=rawopts,reportopts_=ropts} j = do
_ -> do
-- multi column balance report
let report = multiBalanceReport ropts (queryFromOpts d ropts) j
-- With --value-at=transaction, convert all amounts to value before summing them.
let j' | value_at_ == AtTransaction =
error' "sorry, --value-at=transaction with balance reports is not yet supported" -- journalValueAtTransactionDate ropts j
| otherwise = j
let report = multiBalanceReport ropts (queryFromOpts d ropts) j'
render = case format of
"csv" -> (++ "\n") . printCSV . multiBalanceReportAsCsv ropts
"html" -> (++ "\n") . TL.unpack . L.renderText . multiBalanceReportAsHtml ropts

View File

@ -4,7 +4,9 @@ A ledger-compatible @register@ command.
-}
{-# LANGUAGE CPP, OverloadedStrings #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
module Hledger.Cli.Commands.Register (
@ -53,13 +55,19 @@ registermode = hledgerCommandMode
-- | Print a (posting) register report.
register :: CliOpts -> Journal -> IO ()
register opts@CliOpts{reportopts_=ropts} j = do
register opts@CliOpts{reportopts_=ropts@ReportOpts{..}} j = do
d <- getCurrentDay
let fmt = outputFormatFromOpts opts
render | fmt=="csv" = const ((++"\n") . printCSV . postingsReportAsCsv)
| fmt=="html" = const $ error' "Sorry, HTML output is not yet implemented for this kind of report." -- TODO
| otherwise = postingsReportAsText
writeOutput opts $ render opts $ postingsReport ropts (queryFromOpts d ropts) j
-- For register reports with --value-at=transaction,
-- convert all amounts to value before summing them.
j' | value_at_ == AtTransaction = journalValueAtTransactionDate ropts j
| otherwise = j
writeOutput opts $ render opts $ postingsReport ropts (queryFromOpts d ropts) j'
postingsReportAsCsv :: PostingsReport -> CSV
postingsReportAsCsv (_,is) =

View File

@ -25,7 +25,7 @@ import Text.Tabular as T
import Hledger
import Hledger.Cli.Commands.Balance
import Hledger.Cli.CliOptions
import Hledger.Cli.Utils (writeOutput)
import Hledger.Cli.Utils (journalValueAtTransactionDate, writeOutput)
-- | Description of a compound balance report command,
-- from which we generate the command's cmdargs mode and IO action.
@ -207,17 +207,21 @@ compoundBalanceCommand CompoundBalanceCommandSpec{..} opts@CliOpts{reportopts_=r
-- | Run one subreport for a compound balance command in multi-column mode.
-- This returns a MultiBalanceReport.
compoundBalanceSubreport :: ReportOpts -> Query -> Journal -> (Journal -> Query) -> NormalSign -> MultiBalanceReport
compoundBalanceSubreport ropts userq j subreportqfn subreportnormalsign = r'
compoundBalanceSubreport ropts@ReportOpts{..} userq j subreportqfn subreportnormalsign = r'
where
-- With --value-at=transaction and a periodic report, convert all amounts to value before summing them.
j' | value_at_ == AtTransaction && interval_ /= NoInterval = journalValueAtTransactionDate ropts j
| otherwise = j
-- force --empty to ensure same columns in all sections
ropts' = ropts { empty_=True, normalbalance_=Just subreportnormalsign }
-- run the report
q = And [subreportqfn j, userq]
r@(MultiBalanceReport (dates, rows, totals)) = multiBalanceReport ropts' q j
q = And [subreportqfn j', userq]
r@(MultiBalanceReport (dates, rows, totals)) = multiBalanceReport ropts' q j'
-- if user didn't specify --empty, now remove the all-zero rows, unless they have non-zero subaccounts
-- in this report
r' | empty_ ropts = r
| otherwise = MultiBalanceReport (dates, rows', totals)
r' | empty_ = r
| otherwise = MultiBalanceReport (dates, rows', totals)
where
nonzeroaccounts =
dbg1 "nonzeroaccounts" $

View File

@ -1,4 +1,5 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-|
@ -12,8 +13,8 @@ module Hledger.Cli.Utils
withJournalDo,
writeOutput,
journalTransform,
-- journalApplyValue,
journalAddForecast,
journalValueAtTransactionDate,
journalReload,
journalReloadIfChanged,
journalFileIsNewer,
@ -120,24 +121,23 @@ anonymise j
where
anon = T.pack . flip showHex "" . (fromIntegral :: Int -> Word32) . hash
-- TODO move journalApplyValue and friends to Hledger.Data.Journal ?
-- They are here because they use ReportOpts
-- journalApplyValue and friends are here not in Hledger.Data.Journal
-- because they use ReportOpts.
-- XXX we might still use this for --value-date=transaction
-- -- | Convert all the journal's posting amounts to their market value as of
-- -- each posting's date.
-- -- Cf http://hledger.org/manual.html#market-value
-- journalApplyValue :: ReportOpts -> Journal -> IO Journal
-- journalApplyValue ropts j = do
-- today <- getCurrentDay
-- mspecifiedenddate <- specifiedEndDate ropts
-- let d = fromMaybe today mspecifiedenddate
-- -- prices are in parse order - sort into date then parse order,
-- -- reversed for quick lookup of the latest price.
-- ps = reverse $ sortOn mpdate $ jmarketprices j
-- convert | value_ ropts = overJournalAmounts (amountValue ps d)
-- | otherwise = id
-- return $ convert j
-- | Convert all the journal's posting amounts to their market value
-- as of each posting's date. Needed when converting some periodic
-- reports to value, when --value-at=transaction (only).
-- See eg Register.hs.
journalValueAtTransactionDate :: ReportOpts -> Journal -> Journal
journalValueAtTransactionDate ReportOpts{..} j@Journal{..}
| value_at_ /= AtTransaction = j
| otherwise = j{jtxns = map txnvalue jtxns}
where
txnvalue t@Transaction{..} = t{tpostings=map postingvalue tpostings}
postingvalue p@Posting{..} = p{pamount=mixedAmountValue prices (postingDate p) pamount}
-- prices are in parse order - sort into date then parse order,
-- reversed for quick lookup of the latest price.
prices = reverse $ sortOn mpdate jmarketprices
-- | Generate periodic transactions from all periodic transaction rules in the journal.
-- These transactions are added to the in-memory Journal (but not the on-disk file).

View File

@ -501,12 +501,10 @@ The precise effect of the keywords is command-specific, but here is their genera
- `--value-at=transaction` (or `t`)
: Use the prices as of each transaction date (more precisely, each [posting date](/journal.html#posting-dates)).
: (Currently not supported with: balance commands, periodic register reports.)
- `--value-at=period` (or `p`)
: Use the prices as of the last day of the report period (or each subperiod).
: When no report period is specified, this will be the journal's last transaction date.
: (Currently not supported with: periodic register reports.)
- `--value-at=now` (or `n`)
: Use the prices as of today's date when the report is generated. This is the default.
@ -600,6 +598,23 @@ $ hledger -f- print --value-at=2000-01-15
```
### Reports supporting --value-at
Not all combinations of valuation date and hledger report modes are
supported or well understood at present
([#329](https://github.com/simonmichael/hledger/issues/329)).
Here are the ones currently supported
("print", "register", and "balance" here mean all commands of that general type):
| Report type | `--value-at=` `transaction`&nbsp; | `--value-at=` `period`&nbsp; | `--value-at=` `DATE`/`now`&nbsp; |
|---------------------------------------------------------|:---------------------------------:|:----------------------------:|:--------------------------------:|
| print | Y | Y | Y |
| register | Y | Y | Y |
| register,&nbsp;multiperiod | Y | - | Y |
| balance | Y | Y | Y |
| balance,&nbsp;multiperiod | - | Y | Y |
| balance,&nbsp;multiperiod,&nbsp;-T/-A | - | - | Y |
| register/balance,&nbsp;multiperiod,&nbsp;-T/-A,&nbsp;-H | ? | ? | ? |
## Combining -B and -V

View File

@ -113,9 +113,11 @@ $ hledger -f- print -V
>=0
# print --value-at
# --value-at tests
<
P 2000/01/01 A 1 B
P 2000-01-15 A 5 B
P 2000/02/01 A 2 B
P 2000/03/01 A 3 B
P 2000/04/01 A 4 B
@ -129,7 +131,9 @@ P 2000/04/01 A 4 B
2000/03/01
(a) 1 A
# 9. value with prices on transaction (posting) dates
# print
# 9. print value using prices on transaction (posting) dates
$ hledger -f- print --value-at=transaction
2000/01/01
(a) 1 B
@ -142,7 +146,7 @@ $ hledger -f- print --value-at=transaction
>=0
# 10. value with prices on last day of report period (2000-02-29)
# 10. print value using prices on last day of report period (2000-02-29)
$ hledger -f- print --value-at=period date:2000/01-2000/03
2000/01/01
(a) 2 B
@ -152,7 +156,7 @@ $ hledger -f- print --value-at=period date:2000/01-2000/03
>=0
# 11. value with prices on last day of report period with no period
# 11. print value using prices on last day of report period (no period specified)
# specified - uses last day of journal (2000-03-01)
$ hledger -f- print --value-at=period
2000/01/01
@ -166,8 +170,21 @@ $ hledger -f- print --value-at=period
>=0
# 12. value with prices on current date
# (this test assumes today's date is >= 2000-04-01)
# 12. print value using prices on a specified date
$ hledger -f- print --value-at=2000-01-15
2000/01/01
(a) 5 B
2000/02/01
(a) 5 B
2000/03/01
(a) 5 B
>=0
# 13. print value using prices today
# (assuming today's date is >= 2000-04-01)
$ hledger -f- print --value-at=now
2000/01/01
(a) 4 B
@ -180,45 +197,147 @@ $ hledger -f- print --value-at=now
>=0
# 13. value with prices on a custom date
$ hledger -f- print --value-at=2000-01-15
2000/01/01
(a) 1 B
# register
2000/02/01
(a) 1 B
2000/03/01
(a) 1 B
>=0
# 14. multicolumn balance report with default value
$ hledger -f- bal -M -V
Balance changes in 2000q1:
|| Jan Feb Mar
===++===============
a || 4 B 4 B 4 B
---++---------------
|| 4 B 4 B 4 B
# 15. multicolumn balance report valued at transaction is not supported
$ hledger -f- bal -M --value-at=transaction
>2 /not yet supported with balance reports/
>=1
# 14. register report valued at transaction.
# Shows the running total of the posting amount values (not the values
# of the running total).
$ hledger -f- reg --value-at=transaction
2000/01/01 (a) 1 B 1 B
2000/02/01 (a) 2 B 3 B
2000/03/01 (a) 3 B 6 B
# 16. multicolumn balance report valued at period end
# 15. register report valued at period end
$ hledger -f- reg --value-at=period
2000/01/01 (a) 3 B 3 B
2000/02/01 (a) 3 B 6 B
2000/03/01 (a) 3 B 9 B
# 16. register report valued at specified date
$ hledger -f- reg --value-at=2000-01-15
2000/01/01 (a) 5 B 5 B
2000/02/01 (a) 5 B 10 B
2000/03/01 (a) 5 B 15 B
# 17. register report valued today
$ hledger -f- reg --value-at=now
2000/01/01 (a) 4 B 4 B
2000/02/01 (a) 4 B 8 B
2000/03/01 (a) 4 B 12 B
# 18. register report valued at default date (same as above)
$ hledger -f- reg -V
2000/01/01 (a) 4 B 4 B
2000/02/01 (a) 4 B 8 B
2000/03/01 (a) 4 B 12 B
# register, periodic
# 19. periodic register report valued at transaction
$ hledger -f- reg --value-at=transaction -M
2000/01 a 1 B 1 B
2000/02 a 2 B 3 B
2000/03 a 3 B 6 B
# 20. periodic register report valued at period end
$ hledger -f- reg --value-at=period -M
>2 /not yet supported/
>=1
# XXX
# 2000/01 a 5 B 5 B
# 2000/02 a 2 B 7 B
# 2000/03 a 3 B 10 B
# 21. periodic register report valued at specified date
$ hledger -f- reg --value-at=2000-01-15 -M
2000/01 a 5 B 5 B
2000/02 a 5 B 10 B
2000/03 a 5 B 15 B
# 22. periodic register report valued today
$ hledger -f- reg --value-at=now -M
2000/01 a 4 B 4 B
2000/02 a 4 B 8 B
2000/03 a 4 B 12 B
# 23. periodic register report valued at default date (same as above)
$ hledger -f- reg -V -M
2000/01 a 4 B 4 B
2000/02 a 4 B 8 B
2000/03 a 4 B 12 B
# balance
# 24. single column balance report valued at transaction
$ hledger -f- bal --value-at=transaction
6 B a
--------------------
6 B
# 25. single column balance report valued at period end
$ hledger -f- bal --value-at=period
9 B a
--------------------
9 B
# 26. single column balance report valued at specified date
$ hledger -f- bal --value-at=2000-01-15
15 B a
--------------------
15 B
# 27. single column balance report valued today
$ hledger -f- bal --value-at=now
12 B a
--------------------
12 B
# 28. single column balance report valued at default date (same as above)
$ hledger -f- bal -V
12 B a
--------------------
12 B
# balance, periodic
# 29. multicolumn balance report valued at transaction
$ hledger -f- bal -MTA --value-at=transaction
>2 /not yet supported/
>=1
# Balance changes in 2000q1:
#
# || Jan Feb Mar Total Average
# ===++=================================
# a || 1 B 2 B 3 B 6 B 2 B
# ---++---------------------------------
# || 1 B 2 B 3 B 6 B 2 B
# 30. multicolumn balance report valued at period end
$ hledger -f- bal -M --value-at=period
Balance changes in 2000q1:
|| Jan Feb Mar
===++===============
a || 2 B 3 B 4 B
a || 5 B 2 B 3 B
---++---------------
|| 2 B 3 B 4 B
|| 5 B 2 B 3 B
# 17. multicolumn balance report valued at today
# 31. multicolumn balance report valued at period end with -T or -A
$ hledger -f- bal -M --value-at=period -TA
>2 /not yet supported/
>=1
# 32. multicolumn balance report valued at other date
$ hledger -f- bal -M --value-at=2000-01-15
Balance changes in 2000q1:
|| Jan Feb Mar
===++===============
a || 5 B 5 B 5 B
---++---------------
|| 5 B 5 B 5 B
# 33. multicolumn balance report valued today (with today >= 2000-04-01)
$ hledger -f- bal -M --value-at=now
Balance changes in 2000q1:
@ -228,94 +347,13 @@ Balance changes in 2000q1:
---++---------------
|| 4 B 4 B 4 B
# 18. multicolumn balance report valued at other date
$ hledger -f- bal -M --value-at=2000-01-15
# 34. multicolumn balance report valued at default date (same as above)
$ hledger -f- bal -M -V
Balance changes in 2000q1:
|| Jan Feb Mar
===++===============
a || 1 B 1 B 1 B
a || 4 B 4 B 4 B
---++---------------
|| 1 B 1 B 1 B
# 19. single column balance report with default value
$ hledger -f- bal -V
12 B a
--------------------
12 B
# 20. single column balance report valued at transaction is not supported
$ hledger -f- bal --value-at=transaction
>2 /not yet supported with balance reports/
>=1
# 21. single column balance report valued at period end
$ hledger -f- bal --value-at=period
9 B a
--------------------
9 B
# 22. single column balance report valued at today
$ hledger -f- bal --value-at=now
12 B a
--------------------
12 B
# 23. single column balance report valued at other date
$ hledger -f- bal --value-at=2000-01-15
3 B a
--------------------
3 B
# 24. register report with default value
$ hledger -f- reg -V
2000/01/01 (a) 4 B 4 B
2000/02/01 (a) 4 B 8 B
2000/03/01 (a) 4 B 12 B
# 25. register report valued at transaction
$ hledger -f- reg --value-at=transaction
2000/01/01 (a) 1 B 1 B
2000/02/01 (a) 2 B 4 B
2000/03/01 (a) 3 B 9 B
# 26. register report valued at period end
$ hledger -f- reg --value-at=period
2000/01/01 (a) 3 B 3 B
2000/02/01 (a) 3 B 6 B
2000/03/01 (a) 3 B 9 B
# 27. register report valued at today
$ hledger -f- reg --value-at=now
2000/01/01 (a) 4 B 4 B
2000/02/01 (a) 4 B 8 B
2000/03/01 (a) 4 B 12 B
# 28. register report valued at other date
$ hledger -f- reg --value-at=2000-01-15
2000/01/01 (a) 1 B 1 B
2000/02/01 (a) 1 B 2 B
2000/03/01 (a) 1 B 3 B
# 29. periodic register report with default value
$ hledger -f- reg -V -Q
2000q1 a 12 B 12 B
# 30. periodic register report valued at transaction
$ hledger -f- reg --value-at=transaction -Q
>2 /not yet supported with periodic register reports/
>=1
# 31. periodic register report valued at period end
$ hledger -f- reg --value-at=period -Q
>2 /not yet supported with periodic register reports/
>=1
# 32. periodic register report valued at today
$ hledger -f- reg --value-at=now -Q
2000q1 a 12 B 12 B
# 33. periodic register report valued at other date
$ hledger -f- reg --value-at=2000-01-15 -Q
2000q1 a 3 B 3 B
|| 4 B 4 B 4 B