From 4a86fe57a1b303bbfc983fba5e2ca4d35aee2416 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 23 Apr 2020 14:44:30 -0700 Subject: Add two (for the moment undocumented) functions: - commodity_price(NAME, DATE) - set_commodity_price(NAME, DATE) Using these two I am able to compute rate of return over a period of transactions, taking additional deposits and withdrawals into account, using the following automated transactions: P 2019-12-31 12:00:00 ROI $1.00 2020-01-01 Start of record (ROI) 0 ROI = expr date >= [2020/01/01] && account =~ /Broker:Cash$/ and any(account =~ /Assets:Checking/) (ROI) (1 ROI * (amount / commodity_price(1 ROI, date))) = expr date >= [2020/01/01] && account =~ /:Capital:/ (ROI) (set_commodity_price(1 ROI, date, ((commodity_price(1 ROI, date) * account("ROI").amount) - amount) / account("ROI").amount) || 0 ROI) --- src/report.cc | 23 +++++++++++++++++++++++ src/report.h | 2 ++ 2 files changed, 25 insertions(+) (limited to 'src') diff --git a/src/report.cc b/src/report.cc index c5d6d14e..8c35f214 100644 --- a/src/report.cc +++ b/src/report.cc @@ -848,6 +848,25 @@ value_t report_t::fn_commodity(call_scope_t& args) return string_value(args.get(0).commodity().symbol()); } +value_t report_t::fn_commodity_price(call_scope_t& args) +{ + optional price_point + = commodity_pool_t::current_pool->commodity_price_history.find_price + (args.get(0).commodity(), args.get(1)); + if (price_point) { + return price_point->price; + } else { + return amount_t(); + } +} + +value_t report_t::fn_set_commodity_price(call_scope_t& args) +{ + args.get(0).commodity().add_price( + args.get(1), args.get(2), true); + return NULL_VALUE; +} + value_t report_t::fn_clear_commodity(call_scope_t& args) { amount_t amt(args.get(0)); @@ -1399,6 +1418,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return WRAP_FUNCTOR(fn_cyan); else if (is_eq(p, "commodity")) return MAKE_FUNCTOR(report_t::fn_commodity); + else if (is_eq(p, "commodity_price")) + return MAKE_FUNCTOR(report_t::fn_commodity_price); else if (is_eq(p, "ceiling")) return MAKE_FUNCTOR(report_t::fn_ceiling); else if (is_eq(p, "clear_commodity")) @@ -1501,6 +1522,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return MAKE_FUNCTOR(report_t::fn_strip); else if (is_eq(p, "should_bold")) return MAKE_FUNCTOR(report_t::fn_should_bold); + else if (is_eq(p, "set_commodity_price")) + return MAKE_FUNCTOR(report_t::fn_set_commodity_price); break; case 't': diff --git a/src/report.h b/src/report.h index 5325c3a2..c1dc75c2 100644 --- a/src/report.h +++ b/src/report.h @@ -189,6 +189,8 @@ public: value_t fn_ansify_if(call_scope_t& scope); value_t fn_percent(call_scope_t& scope); value_t fn_commodity(call_scope_t& scope); + value_t fn_commodity_price(call_scope_t& scope); + value_t fn_set_commodity_price(call_scope_t& scope); value_t fn_nail_down(call_scope_t& scope); value_t fn_lot_date(call_scope_t& scope); value_t fn_lot_price(call_scope_t& scope); -- cgit v1.2.3