[balsheet-pnl] pnl columns should retrieve appropriate price.

Preamble: the profit&loss list of dates starts from starting_date,
adds Delta time until end_date. i.e. monthly pnl from 1-jan to 31-dec
generates list 1-jan 1-feb 1-mar etc.

The pnl columns refer to period ColumnDate to next ColumnDate, less 1
day. i.e. 1-jan to 31-jan, 1-feb to 28-feb, 1-mar to 31-mar etc.

The pnl columns must convert to report-currency using price retrieved
on the period end_date rather than the next start_date. i.e. Old code
would retrieve 1-feb price for 1-jan to 31-jan column. This is
incorrect. This commit ensures that the 1-jan to 31-jan retrieves
price on 31-jan.
This commit is contained in:
Christopher Lam 2021-02-15 19:10:17 +08:00
parent 6efdafb9b4
commit b4e99a3048
2 changed files with 25 additions and 16 deletions

View File

@ -811,6 +811,18 @@ also show overall period profit & loss."))
(map xaccAccountGetCommodity accounts) enddate
#f #f)))
;; from col-idx, find effective date to retrieve pricedb
;; entry or to limit transactions to calculate average-cost
;; or weighted-average
(col-idx->price-date
(lambda (col-idx)
(cond
((eq? price-source 'pricedb-latest) (current-time))
((eq? col-idx 'overall-period) enddate)
((eq? report-type 'balsheet) (vector-ref report-dates-vec col-idx))
((eq? report-type 'pnl)
(decdate (vector-ref report-dates-vec (1+ col-idx)) DayDelta)))))
;; this function will convert the monetary found at col-idx
;; into report-currency if the latter exists. The price
;; applicable to the col-idx column is used. If the monetary
@ -824,11 +836,7 @@ also show overall period profit & loss."))
(has-price? (gnc:gnc-monetary-commodity monetary))
(exchange-fn
monetary common-currency
(cond
((eq? price-source 'pricedb-latest) (current-time))
((eq? col-idx 'overall-period) enddate)
((eq? report-type 'balsheet) (vector-ref report-dates-vec col-idx))
((eq? report-type 'pnl) (vector-ref report-dates-vec (1+ col-idx))))))))
(col-idx->price-date col-idx)))))
;; the following function generates an gnc:html-text object
;; to dump exchange rate for a particular column. From the
@ -843,14 +851,15 @@ also show overall period profit & loss."))
(lambda (commodity)
(let ((orig-monetary (gnc:make-gnc-monetary commodity 1)))
(if (has-price? commodity)
(let* ((conv-monetary (convert-curr-fn orig-monetary col-idx))
(conv-amount (gnc:gnc-monetary-amount conv-monetary)))
(let ((price (gnc:case-price-fn
price-source common-currency
(col-idx->price-date col-idx))))
(gnc:html-text-append!
cell
(format #f "~a ~a"
(gnc:monetary->string orig-monetary)
(gnc:default-price-renderer common-currency
conv-amount))))
(price commodity)))))
(gnc:html-text-append!
cell
(string-append

View File

@ -529,7 +529,7 @@
"$2,609.00" "$0.00" "$100.00" "$11,000.30" "$2,000.00" "$9,000.30"
"30 FUNDS " "$297.03" "$297.03" "#200.00 " "$100,000.00" "$116,006.33"
"$9,500.00" "$9,500.00" "$500.00" "$9,000.00" "$9,500.00" "$103,600.00"
"$2,906.33" "$0.00" "$106,506.33" "$116,006.33" "#1.00 $1.4900"
"$2,906.33" "$0.00" "$106,506.33" "$116,006.33" "#1.00 $1 + 49/101"
"1 FUNDS $300.0100")
(sxml->table-row-col sxml 1 #f 3))
(test-equal "bal-1/1/72"
@ -537,8 +537,8 @@
"$2,609.00" "$0.00" "$100.00" "$12,396.63" "$2,000.00" "$10,396.63"
"30 FUNDS " "$331.37" "$331.37" "#200.00 " "$100,000.00" "$117,437.00"
"$9,500.00" "$9,500.00" "$500.00" "$9,000.00" "$9,500.00" "$103,600.00"
"$4,337.00" "$0.00" "$107,937.00" "$117,437.00" "#1.00 $1.6600"
"1 FUNDS $346.5500")
"$4,337.00" "$0.00" "$107,937.00" "$117,437.00" "#1.00 $1 + 67/102"
"1 FUNDS $346 + 56/101")
(sxml->table-row-col sxml 1 #f 4)))
(set-option! multi-bs-options "General" "Period order is most recent first" #t)
@ -562,7 +562,7 @@
"$1,190.00" "$1,190.00" "#700.00 " "$100,000.00" "$122,743.52"
"$9,500.00" "$9,500.00" "$500.00" "$9,000.00" "$9,500.00"
"$103,600.00" "$8,373.52" "$1,270.00" "$113,243.52" "$122,743.52"
"#1.00 $1.7000" "1 FUNDS $480.8200")
"#1.00 $1.7000" "1 FUNDS $480 + 85/104")
(sxml->table-row-col sxml 1 #f 2)))))
(define (multicol-pnl-tests)
@ -622,26 +622,26 @@
(let ((sxml (options->sxml multicol-balsheet-uuid multi-bs-options
"multicol pnl weighted-average")))
(test-equal "weighted average exchange-rate"
(list "#1.00 $1 + 569/1100" "1 FUNDS $235 + 3/7")
'("#1.00 $1.4990" "1 FUNDS $235 + 3/7")
(sxml->table-row-col sxml 1 -2 -1)))
(set-option! multi-bs-options "Commodities" "Price Source" 'average-cost)
(let ((sxml (options->sxml multicol-balsheet-uuid multi-bs-options
"multicol pnl average-cost")))
(test-equal "average-cost exchange-rate"
'("#1.00 $1.2100" "1 FUNDS $203 + 1/3")
'("#1.00 $1.4550" "1 FUNDS $203 + 1/3")
(sxml->table-row-col sxml 1 -2 -1)))
(set-option! multi-bs-options "Commodities" "Price Source" 'pricedb-nearest)
(let ((sxml (options->sxml multicol-balsheet-uuid multi-bs-options
"multicol pnl pricedb-nearest")))
(test-equal "pricedb-nearest exchange-rate"
'("#1.00 $1.7000" "1 FUNDS $480.8200")
'("#1.00 $1.7000" "1 FUNDS $480 + 85/104")
(sxml->table-row-col sxml 1 -2 -1)))
(set-option! multi-bs-options "Commodities" "Price Source" 'pricedb-latest)
(let ((sxml (options->sxml multicol-balsheet-uuid multi-bs-options
"multicol pnl pricedb-latest")))
(test-equal "pricedb-latest exchange-rate"
'("#1.00 $1.7000" "1 FUNDS $480.8200")
'("#1.00 $1.7000" "1 FUNDS $480 + 85/104")
(sxml->table-row-col sxml 1 -2 -1)))))