holding: Add multi-currency support for average costs calculations. #2153
Reference in New Issue
Block a user
Delete Branch "convert-avg-cost"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR adds multi-currency support when calculating for the cost basis
Fixes: #2051.
Thanks for the changes here. Just a few points of feedback:
holding.avg_costandholding.weighted_avg_cost. That way in the future we can provide a UI for the user to select which type of calculation they want.BalanceSheetandIncomeStatementclasses, but instead, we'd call itPortfolioand do one big aggregate query that calculates all the cost basis across all holdings, then these model-specific methods simply "look up" the values needed from those aggregated results that are queried once, cached, and read many times by the various holdings.Ultimately, I think moving to a weighted average introduces quite a bit of hidden complexity, so I think the highest impact thing we can do if we're looking for a quick improvement is integrating
exchange_ratesinto the existing simple avg. query.@zachgoll Thanks for the feedback on this PR! For now, I've moved forward with just integrating exchange_rates into the existing avg_cost and remove the weighted average cost as I'm not sure where would be a good place for that sort of calculation. However I would be happy to introduce it to the code base later on :)
Overall changes look good now thanks! Just left one improvement we can make to the query.
@@ -34,3 +41,4 @@.average("trades.price * COALESCE(exchange_rates.rate, 1)")Money.new(avg_cost || price, currency)endFor clarity of the ownership here, can we use some of the existing query helpers (see entryable)?
Also, check
entry.date <= ?I think that should beentries.date@@ -34,3 +41,4 @@.average("trades.price * COALESCE(exchange_rates.rate, 1)")Money.new(avg_cost || price, currency)endUpdated to use
with_entryandentriesin the latest commit.I think entry was ok as it was just aliased to
entryinstead ofentries. But I've updated it to useentriesinstead.@@ -27,10 +27,18 @@ class Holding < ApplicationRecordI'd like to scope this to the account just to stay consistent with our query patterns elsewhere in the app.
Thanks for the suggestions @zachgoll! I've updated the PR to follow the suggestions.
Awesome, looks great!