Files

74 lines
3.0 KiB
Python

from app.extensions import db
from datetime import datetime
class Investment(db.Model):
__tablename__ = 'investments'
id = db.Column(db.Integer, primary_key=True)
# Optional link to a PFM account (e.g. Schwab Individual, Schwab Roth IRA).
# NULL means the holding is not tied to a specific account.
account_id = db.Column(db.Integer, db.ForeignKey('accounts.id'), nullable=True, index=True)
asset_name = db.Column(db.String(100), nullable=False)
ticker = db.Column(db.String(20), nullable=True)
asset_type = db.Column(
db.Enum('stock', 'etf', 'crypto', 'real_estate', 'bond', 'cash', 'other'),
nullable=False,
default='stock'
)
shares = db.Column(db.Numeric(18, 8), nullable=False, default=0)
avg_cost_basis = db.Column(db.Numeric(15, 4), nullable=False, default=0)
current_price = db.Column(db.Numeric(15, 4), nullable=True)
last_price_update = db.Column(db.DateTime, nullable=True)
notes = db.Column(db.Text, nullable=True)
is_active = db.Column(db.Boolean, default=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
account = db.relationship('Account', foreign_keys=[account_id])
inv_transactions = db.relationship('InvestmentTransaction', back_populates='investment',
lazy='dynamic', cascade='all, delete-orphan')
@property
def total_cost(self):
return float(self.shares) * float(self.avg_cost_basis)
@property
def current_value(self):
if self.current_price:
return float(self.shares) * float(self.current_price)
return self.total_cost
@property
def unrealized_gain(self):
return self.current_value - self.total_cost
@property
def unrealized_gain_pct(self):
if self.total_cost == 0:
return 0
return round((self.unrealized_gain / self.total_cost) * 100, 2)
def __repr__(self):
return f'<Investment {self.asset_name}>'
class InvestmentTransaction(db.Model):
__tablename__ = 'investment_transactions'
id = db.Column(db.Integer, primary_key=True)
investment_id = db.Column(db.Integer, db.ForeignKey('investments.id'), nullable=False)
transaction_type = db.Column(db.Enum('buy', 'sell', 'dividend', 'split'), nullable=False)
shares = db.Column(db.Numeric(18, 8), nullable=False)
price_per_share = db.Column(db.Numeric(15, 4), nullable=False)
total_amount = db.Column(db.Numeric(15, 2), nullable=False)
fees = db.Column(db.Numeric(10, 2), default=0.00)
date = db.Column(db.Date, nullable=False, index=True)
notes = db.Column(db.String(255), nullable=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
investment = db.relationship('Investment', back_populates='inv_transactions')
def __repr__(self):
return f'<InvTransaction {self.transaction_type} {self.shares}@{self.price_per_share}>'