1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-07 22:45:20 +02:00

Investment Portfolio Sync (#974)

* Add investment portfolio models

* Add portfolio to demo data

* Setup initial tests

* Rough sketch of sync logic

* Clean up trade sync logic

* Add trade validation

* Integrate trades into sync process
This commit is contained in:
Zach Gollwitzer 2024-07-16 09:26:49 -04:00 committed by GitHub
parent d0bc959bee
commit 47523f64c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 591 additions and 56 deletions

View file

@ -27,13 +27,9 @@ class Account::Balance::Syncer
attr_reader :sync_start_date, :account
def upsert_balances!(balances)
current_time = Time.now
balances_to_upsert = balances.map do |balance|
{
date: balance.date,
balance: balance.balance,
currency: balance.currency,
updated_at: Time.now
}
balance.attributes.slice("date", "balance", "currency").merge("updated_at" => current_time)
end
account.balances.upsert_all(balances_to_upsert, unique_by: %i[account_id date currency])
@ -49,9 +45,9 @@ class Account::Balance::Syncer
return valuation.amount if valuation
return derived_sync_start_balance(entries) unless prior_balance
transactions = entries.select { |e| e.date == date && e.account_transaction? }
entries = entries.select { |e| e.date == date }
prior_balance - net_transaction_flows(transactions)
prior_balance - net_entry_flows(entries)
end
def calculate_daily_balances
@ -95,19 +91,19 @@ class Account::Balance::Syncer
end
def derived_sync_start_balance(entries)
transactions = entries.select { |e| e.account_transaction? && e.date > sync_start_date }
transactions_and_trades = entries.reject { |e| e.account_valuation? }.select { |e| e.date > sync_start_date }
account.balance + net_transaction_flows(transactions)
account.balance + net_entry_flows(transactions_and_trades)
end
def find_prior_balance
account.balances.where("date < ?", sync_start_date).order(date: :desc).first&.balance
end
def net_transaction_flows(transactions, target_currency = account.currency)
converted_transaction_amounts = transactions.map { |t| t.amount_money.exchange_to(target_currency, date: t.date) }
def net_entry_flows(entries, target_currency = account.currency)
converted_entry_amounts = entries.map { |t| t.amount_money.exchange_to(target_currency, date: t.date) }
flows = converted_transaction_amounts.sum(&:amount)
flows = converted_entry_amounts.sum(&:amount)
account.liability? ? flows * -1 : flows
end