mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 07:25:19 +02:00
Remove bad abstraction
This commit is contained in:
parent
c8b1e1d059
commit
64147758a3
6 changed files with 178 additions and 101 deletions
|
@ -1,35 +0,0 @@
|
||||||
class Balance::BaseCalculator
|
|
||||||
attr_reader :account
|
|
||||||
|
|
||||||
def initialize(account)
|
|
||||||
@account = account
|
|
||||||
end
|
|
||||||
|
|
||||||
def calculate
|
|
||||||
Rails.logger.tagged(self.class.name) do
|
|
||||||
calculate_balances
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def sync_cache
|
|
||||||
@sync_cache ||= Balance::SyncCache.new(account)
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_balance(date, cash_balance, holdings_value)
|
|
||||||
Balance.new(
|
|
||||||
account_id: account.id,
|
|
||||||
date: date,
|
|
||||||
balance: holdings_value + cash_balance,
|
|
||||||
cash_balance: cash_balance,
|
|
||||||
currency: account.currency
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def calculate_next_balance(prior_balance, transactions, direction: :forward)
|
|
||||||
flows = transactions.sum(&:amount)
|
|
||||||
negated = direction == :forward ? account.asset? : account.liability?
|
|
||||||
flows *= -1 if negated
|
|
||||||
prior_balance + flows
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,4 +1,16 @@
|
||||||
class Balance::ForwardCalculator < Balance::BaseCalculator
|
class Balance::ForwardCalculator
|
||||||
|
attr_reader :account
|
||||||
|
|
||||||
|
def initialize(account)
|
||||||
|
@account = account
|
||||||
|
end
|
||||||
|
|
||||||
|
def calculate
|
||||||
|
Rails.logger.tagged("Balance::ForwardCalculator") do
|
||||||
|
calculate_balances
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def calculate_balances
|
def calculate_balances
|
||||||
current_cash_balance = 0
|
current_cash_balance = 0
|
||||||
|
@ -25,4 +37,25 @@ class Balance::ForwardCalculator < Balance::BaseCalculator
|
||||||
|
|
||||||
@balances
|
@balances
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sync_cache
|
||||||
|
@sync_cache ||= Balance::SyncCache.new(account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_balance(date, cash_balance, holdings_value)
|
||||||
|
Balance.new(
|
||||||
|
account_id: account.id,
|
||||||
|
date: date,
|
||||||
|
balance: holdings_value + cash_balance,
|
||||||
|
cash_balance: cash_balance,
|
||||||
|
currency: account.currency
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def calculate_next_balance(prior_balance, transactions, direction: :forward)
|
||||||
|
flows = transactions.sum(&:amount)
|
||||||
|
negated = direction == :forward ? account.asset? : account.liability?
|
||||||
|
flows *= -1 if negated
|
||||||
|
prior_balance + flows
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,16 @@
|
||||||
class Balance::ReverseCalculator < Balance::BaseCalculator
|
class Balance::ReverseCalculator
|
||||||
|
attr_reader :account
|
||||||
|
|
||||||
|
def initialize(account)
|
||||||
|
@account = account
|
||||||
|
end
|
||||||
|
|
||||||
|
def calculate
|
||||||
|
Rails.logger.tagged("Balance::ReverseCalculator") do
|
||||||
|
calculate_balances
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def calculate_balances
|
def calculate_balances
|
||||||
current_cash_balance = account.cash_balance
|
current_cash_balance = account.cash_balance
|
||||||
|
@ -35,4 +47,25 @@ class Balance::ReverseCalculator < Balance::BaseCalculator
|
||||||
|
|
||||||
@balances
|
@balances
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sync_cache
|
||||||
|
@sync_cache ||= Balance::SyncCache.new(account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_balance(date, cash_balance, holdings_value)
|
||||||
|
Balance.new(
|
||||||
|
account_id: account.id,
|
||||||
|
date: date,
|
||||||
|
balance: holdings_value + cash_balance,
|
||||||
|
cash_balance: cash_balance,
|
||||||
|
currency: account.currency
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def calculate_next_balance(prior_balance, transactions, direction: :forward)
|
||||||
|
flows = transactions.sum(&:amount)
|
||||||
|
negated = direction == :forward ? account.asset? : account.liability?
|
||||||
|
flows *= -1 if negated
|
||||||
|
prior_balance + flows
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
class Holding::BaseCalculator
|
|
||||||
attr_reader :account
|
|
||||||
|
|
||||||
def initialize(account)
|
|
||||||
@account = account
|
|
||||||
end
|
|
||||||
|
|
||||||
def calculate
|
|
||||||
Rails.logger.tagged(self.class.name) do
|
|
||||||
holdings = calculate_holdings
|
|
||||||
Holding.gapfill(holdings)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def portfolio_cache
|
|
||||||
@portfolio_cache ||= Holding::PortfolioCache.new(account)
|
|
||||||
end
|
|
||||||
|
|
||||||
def empty_portfolio
|
|
||||||
securities = portfolio_cache.get_securities
|
|
||||||
securities.each_with_object({}) { |security, hash| hash[security.id] = 0 }
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_starting_portfolio
|
|
||||||
empty_portfolio
|
|
||||||
end
|
|
||||||
|
|
||||||
def transform_portfolio(previous_portfolio, trade_entries, direction: :forward)
|
|
||||||
new_quantities = previous_portfolio.dup
|
|
||||||
|
|
||||||
trade_entries.each do |trade_entry|
|
|
||||||
trade = trade_entry.entryable
|
|
||||||
security_id = trade.security_id
|
|
||||||
qty_change = trade.qty
|
|
||||||
qty_change = qty_change * -1 if direction == :reverse
|
|
||||||
new_quantities[security_id] = (new_quantities[security_id] || 0) + qty_change
|
|
||||||
end
|
|
||||||
|
|
||||||
new_quantities
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_holdings(portfolio, date, price_source: nil)
|
|
||||||
portfolio.map do |security_id, qty|
|
|
||||||
price = portfolio_cache.get_price(security_id, date, source: price_source)
|
|
||||||
|
|
||||||
if price.nil?
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
Holding.new(
|
|
||||||
account_id: account.id,
|
|
||||||
security_id: security_id,
|
|
||||||
date: date,
|
|
||||||
qty: qty,
|
|
||||||
price: price.price,
|
|
||||||
currency: price.currency,
|
|
||||||
amount: qty * price.price
|
|
||||||
)
|
|
||||||
end.compact
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +1,65 @@
|
||||||
class Holding::ForwardCalculator < Holding::BaseCalculator
|
class Holding::ForwardCalculator
|
||||||
|
attr_reader :account
|
||||||
|
|
||||||
|
def initialize(account)
|
||||||
|
@account = account
|
||||||
|
end
|
||||||
|
|
||||||
|
def calculate
|
||||||
|
Rails.logger.tagged("Holding::ForwardCalculator") do
|
||||||
|
holdings = calculate_holdings
|
||||||
|
Holding.gapfill(holdings)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def portfolio_cache
|
def portfolio_cache
|
||||||
@portfolio_cache ||= Holding::PortfolioCache.new(account)
|
@portfolio_cache ||= Holding::PortfolioCache.new(account)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def empty_portfolio
|
||||||
|
securities = portfolio_cache.get_securities
|
||||||
|
securities.each_with_object({}) { |security, hash| hash[security.id] = 0 }
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_starting_portfolio
|
||||||
|
empty_portfolio
|
||||||
|
end
|
||||||
|
|
||||||
|
def transform_portfolio(previous_portfolio, trade_entries, direction: :forward)
|
||||||
|
new_quantities = previous_portfolio.dup
|
||||||
|
|
||||||
|
trade_entries.each do |trade_entry|
|
||||||
|
trade = trade_entry.entryable
|
||||||
|
security_id = trade.security_id
|
||||||
|
qty_change = trade.qty
|
||||||
|
qty_change = qty_change * -1 if direction == :reverse
|
||||||
|
new_quantities[security_id] = (new_quantities[security_id] || 0) + qty_change
|
||||||
|
end
|
||||||
|
|
||||||
|
new_quantities
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_holdings(portfolio, date, price_source: nil)
|
||||||
|
portfolio.map do |security_id, qty|
|
||||||
|
price = portfolio_cache.get_price(security_id, date, source: price_source)
|
||||||
|
|
||||||
|
if price.nil?
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
Holding.new(
|
||||||
|
account_id: account.id,
|
||||||
|
security_id: security_id,
|
||||||
|
date: date,
|
||||||
|
qty: qty,
|
||||||
|
price: price.price,
|
||||||
|
currency: price.currency,
|
||||||
|
amount: qty * price.price
|
||||||
|
)
|
||||||
|
end.compact
|
||||||
|
end
|
||||||
|
|
||||||
def calculate_holdings
|
def calculate_holdings
|
||||||
current_portfolio = generate_starting_portfolio
|
current_portfolio = generate_starting_portfolio
|
||||||
next_portfolio = {}
|
next_portfolio = {}
|
||||||
|
|
|
@ -1,4 +1,17 @@
|
||||||
class Holding::ReverseCalculator < Holding::BaseCalculator
|
class Holding::ReverseCalculator
|
||||||
|
attr_reader :account
|
||||||
|
|
||||||
|
def initialize(account)
|
||||||
|
@account = account
|
||||||
|
end
|
||||||
|
|
||||||
|
def calculate
|
||||||
|
Rails.logger.tagged("Holding::ReverseCalculator") do
|
||||||
|
holdings = calculate_holdings
|
||||||
|
Holding.gapfill(holdings)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
# Reverse calculators will use the existing holdings as a source of security ids and prices
|
# Reverse calculators will use the existing holdings as a source of security ids and prices
|
||||||
# since it is common for a provider to supply "current day" holdings but not all the historical
|
# since it is common for a provider to supply "current day" holdings but not all the historical
|
||||||
|
@ -25,6 +38,11 @@ class Holding::ReverseCalculator < Holding::BaseCalculator
|
||||||
holdings
|
holdings
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def empty_portfolio
|
||||||
|
securities = portfolio_cache.get_securities
|
||||||
|
securities.each_with_object({}) { |security, hash| hash[security.id] = 0 }
|
||||||
|
end
|
||||||
|
|
||||||
# Since this is a reverse sync, we start with today's holdings
|
# Since this is a reverse sync, we start with today's holdings
|
||||||
def generate_starting_portfolio
|
def generate_starting_portfolio
|
||||||
holding_quantities = empty_portfolio
|
holding_quantities = empty_portfolio
|
||||||
|
@ -37,4 +55,38 @@ class Holding::ReverseCalculator < Holding::BaseCalculator
|
||||||
|
|
||||||
holding_quantities
|
holding_quantities
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def transform_portfolio(previous_portfolio, trade_entries, direction: :forward)
|
||||||
|
new_quantities = previous_portfolio.dup
|
||||||
|
|
||||||
|
trade_entries.each do |trade_entry|
|
||||||
|
trade = trade_entry.entryable
|
||||||
|
security_id = trade.security_id
|
||||||
|
qty_change = trade.qty
|
||||||
|
qty_change = qty_change * -1 if direction == :reverse
|
||||||
|
new_quantities[security_id] = (new_quantities[security_id] || 0) + qty_change
|
||||||
|
end
|
||||||
|
|
||||||
|
new_quantities
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_holdings(portfolio, date, price_source: nil)
|
||||||
|
portfolio.map do |security_id, qty|
|
||||||
|
price = portfolio_cache.get_price(security_id, date, source: price_source)
|
||||||
|
|
||||||
|
if price.nil?
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
Holding.new(
|
||||||
|
account_id: account.id,
|
||||||
|
security_id: security_id,
|
||||||
|
date: date,
|
||||||
|
qty: qty,
|
||||||
|
price: price.price,
|
||||||
|
currency: price.currency,
|
||||||
|
amount: qty * price.price
|
||||||
|
)
|
||||||
|
end.compact
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue