summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2019-08-03 13:37:58 -0700
committerJohn Wiegley <johnw@newartisans.com>2019-12-06 14:06:22 +0100
commitf77bdf19c307811d4659b6e85d147cdd5eee5ef3 (patch)
tree7a3dcae3901cb1543feed902dce256cf3b751d69 /src
parent6a140f313433e4ac21882d7995dbbb56124b4079 (diff)
downloadfork-ledger-f77bdf19c307811d4659b6e85d147cdd5eee5ef3.tar.gz
fork-ledger-f77bdf19c307811d4659b6e85d147cdd5eee5ef3.tar.bz2
fork-ledger-f77bdf19c307811d4659b6e85d147cdd5eee5ef3.zip
Add --averaged-lot-prices
This joins together lots of the same underlying, averaging the reported price and using the date of the oldest lot.
Diffstat (limited to 'src')
-rw-r--r--src/balance.cc59
-rw-r--r--src/balance.h2
-rw-r--r--src/report.cc11
-rw-r--r--src/report.h9
4 files changed, 81 insertions, 0 deletions
diff --git a/src/balance.cc b/src/balance.cc
index 5f5e6fc9..f0065dc5 100644
--- a/src/balance.cc
+++ b/src/balance.cc
@@ -345,4 +345,63 @@ void put_balance(property_tree::ptree& st, const balance_t& bal)
put_amount(st.add("amount", ""), pair.second);
}
+balance_t average_lot_prices(const balance_t& bal)
+{
+ // First, we split the balance into multiple balances by underlying
+ // commodity.
+ typedef std::map<optional<std::string>,
+ std::pair<amount_t, annotation_t> > balance_map;
+ balance_map bycomm;
+
+ foreach (const balance_t::amounts_map::value_type& pair, bal.amounts) {
+ optional<std::string> sym(pair.first->symbol());
+ amount_t quant(pair.second.strip_annotations(keep_details_t()));
+
+ balance_map::iterator i = bycomm.find(sym);
+ if (i == bycomm.end()) {
+ bycomm.insert(
+ balance_map::value_type(sym, std::make_pair(quant, annotation_t())));
+ i = bycomm.find(sym); // must succeed now
+ } else {
+ (*i).second.first += quant;
+ }
+
+ if (pair.first->has_annotation()) {
+ annotated_commodity_t& acomm(static_cast<annotated_commodity_t&>(*pair.first));
+ annotation_t& ann((*i).second.second);
+
+ if (acomm.details.price) {
+ if (ann.price)
+ ann.price = *ann.price + (*acomm.details.price * quant);
+ else
+ ann.price = *acomm.details.price * quant;
+ }
+
+ if (acomm.details.date) {
+ if (! ann.date || *acomm.details.date < *ann.date)
+ ann.date = *acomm.details.date;
+ }
+ }
+ }
+
+ balance_t result;
+
+ foreach (balance_map::value_type& pair, bycomm) {
+ amount_t amt(pair.second.first);
+ if (! amt.is_realzero()) {
+ if (pair.second.second.price)
+ pair.second.second.price = *pair.second.second.price / amt;
+
+ commodity_t * acomm =
+ commodity_pool_t::current_pool->find_or_create(
+ amt.commodity(), pair.second.second);
+ amt.set_commodity(*acomm);
+
+ result += amt;
+ }
+ }
+
+ return result;
+}
+
} // namespace ledger
diff --git a/src/balance.h b/src/balance.h
index bd373cb9..19b6bd84 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -603,6 +603,8 @@ inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
void put_balance(property_tree::ptree& pt, const balance_t& bal);
+balance_t average_lot_prices(const balance_t& bal);
+
} // namespace ledger
#endif // _BALANCE_H
diff --git a/src/report.cc b/src/report.cc
index cc165184..c5d6d14e 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -563,6 +563,14 @@ value_t report_t::fn_should_bold(call_scope_t& scope)
return false;
}
+value_t report_t::fn_averaged_lots(call_scope_t& args)
+{
+ if (args.has<balance_t>(0))
+ return average_lot_prices(args.get<balance_t>(0));
+ else
+ return args[0];
+}
+
value_t report_t::fn_market(call_scope_t& args)
{
value_t result;
@@ -1130,6 +1138,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
else OPT(average);
else OPT(account_width_);
else OPT(amount_width_);
+ else OPT(average_lot_prices);
break;
case 'b':
OPT(balance_format_);
@@ -1370,6 +1379,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
return MAKE_FUNCTOR(report_t::fn_ansify_if);
else if (is_eq(p, "abs"))
return MAKE_FUNCTOR(report_t::fn_abs);
+ else if (is_eq(p, "averaged_lots"))
+ return MAKE_FUNCTOR(report_t::fn_averaged_lots);
break;
case 'b':
diff --git a/src/report.h b/src/report.h
index 7775e21d..5325c3a2 100644
--- a/src/report.h
+++ b/src/report.h
@@ -202,6 +202,7 @@ public:
value_t fn_to_string(call_scope_t& scope);
value_t fn_to_mask(call_scope_t& scope);
value_t fn_to_sequence(call_scope_t& scope);
+ value_t fn_averaged_lots(call_scope_t& scope);
value_t fn_now(call_scope_t&) {
return terminus;
@@ -298,6 +299,7 @@ public:
HANDLER(limit_).report(out);
HANDLER(lot_dates).report(out);
HANDLER(lot_prices).report(out);
+ HANDLER(average_lot_prices).report(out);
HANDLER(lot_notes).report(out);
HANDLER(lots).report(out);
HANDLER(lots_actual).report(out);
@@ -745,6 +747,13 @@ public:
OPTION(report_t, lot_dates);
OPTION(report_t, lot_prices);
+ OPTION_(report_t, average_lot_prices, DO() {
+ OTHER(lot_prices).on(whence);
+ OTHER(display_amount_)
+ .on(whence, "averaged_lots(display_amount)");
+ OTHER(display_total_)
+ .on(whence, "averaged_lots(display_total)");
+ });
OPTION(report_t, lot_notes);
OPTION(report_t, lots);
OPTION(report_t, lots_actual);