1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-05 13:35:21 +02:00

Basic Portfolio Views (#1000)

* Add holdings tab to account view

* Basic portfolio UI

* Cleanup

* Handle missing holding data

* Remove synced at (implemented in separate pr)

* translations

* Tweak post sync streams

* Remove stale methods from merge conflict
This commit is contained in:
Zach Gollwitzer 2024-07-25 16:46:04 -04:00 committed by GitHub
parent ef4be7948a
commit 7c2091b343
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 582 additions and 86 deletions

View file

@ -1,6 +1,46 @@
class Account::Holding < ApplicationRecord
include Monetizable
monetize :amount
belongs_to :account
belongs_to :security
validates :qty, :currency, presence: true
scope :chronological, -> { order(:date) }
scope :current, -> { where(date: Date.current).order(amount: :desc) }
scope :for, ->(security) { where(security_id: security).order(:date) }
delegate :name, to: :security
delegate :symbol, to: :security
def weight
return nil unless amount
portfolio_value = account.holdings.current.where.not(amount: nil).sum(&:amount)
portfolio_value.zero? ? 1 : amount / portfolio_value * 100
end
# Basic approximation of cost-basis
def avg_cost
avg_cost = account.holdings.for(security).where("date <= ?", date).average(:price)
Money.new(avg_cost, currency)
end
def trend
@trend ||= calculate_trend
end
private
def calculate_trend
return nil unless amount_money
start_amount = qty * avg_cost
TimeSeries::Trend.new \
current: amount_money,
previous: start_amount
end
end

View file

@ -38,14 +38,18 @@ class Account::Holding::Syncer
@portfolio = generate_next_portfolio(@portfolio, trades)
@portfolio.map do |isin, holding|
price = Security::Price.find_by!(date: date, isin: isin).price
trade = trades.find { |trade| trade.account_trade.security_id == holding[:security_id] }
trade_price = trade&.account_trade&.price
price = Security::Price.find_by(date: date, isin: isin)&.price || trade_price
account.holdings.build \
date: date,
security_id: holding[:security_id],
qty: holding[:qty],
price: price,
amount: price * holding[:qty]
amount: price ? (price * holding[:qty]) : nil,
currency: holding[:currency]
end
end
@ -61,6 +65,7 @@ class Account::Holding::Syncer
qty: new_qty,
price: price,
amount: new_qty * price,
currency: entry.currency,
security_id: trade.security_id
}
end
@ -85,6 +90,7 @@ class Account::Holding::Syncer
qty: holding.qty,
price: holding.price,
amount: holding.amount,
currency: holding.currency,
security_id: holding.security_id
}
end

View file

@ -78,6 +78,6 @@ class Account::Sync < ApplicationRecord
partial: "shared/notification",
locals: { type: type, message: message }
)
broadcast_refresh_to account
account.family.broadcast_refresh
end
end