mirror of
https://github.com/wahyd4/links.git
synced 2026-08-09 05:06:16 +10:00
75 lines
2.4 KiB
Python
75 lines
2.4 KiB
Python
from django.db import models
|
|
from django.core.validators import MinValueValidator
|
|
from decimal import Decimal
|
|
|
|
|
|
class Portfolio(models.Model):
|
|
"""Represents an investment account/portfolio (e.g., 'MOMO', 'User IBKR')."""
|
|
name = models.CharField(max_length=100)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
class Meta:
|
|
ordering = ['name']
|
|
|
|
|
|
class Stock(models.Model):
|
|
"""
|
|
Current holdings snapshot for a portfolio.
|
|
Only stores stock_code and quantity - NO price stored.
|
|
Real-time prices fetched from Yahoo Finance on demand.
|
|
"""
|
|
portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, related_name='stocks')
|
|
stock_code = models.CharField(max_length=20, help_text="Stock ticker code, e.g., 'NVDA', '9988.HK'")
|
|
quantity = models.DecimalField(
|
|
max_digits=20,
|
|
decimal_places=6,
|
|
default=Decimal('0'),
|
|
validators=[MinValueValidator(Decimal('0'))],
|
|
help_text="Number of shares held"
|
|
)
|
|
|
|
class Meta:
|
|
unique_together = [('portfolio', 'stock_code')]
|
|
ordering = ['stock_code']
|
|
|
|
def __str__(self):
|
|
return f"{self.stock_code} ({self.portfolio.name})"
|
|
|
|
|
|
class Transaction(models.Model):
|
|
"""
|
|
Historical buy/sell transactions.
|
|
Used to calculate avg_cost and derive P/L on demand.
|
|
"""
|
|
ACTION_BUY = 'BUY'
|
|
ACTION_SELL = 'SELL'
|
|
ACTION_CHOICES = [(ACTION_BUY, 'Buy'), (ACTION_SELL, 'Sell')]
|
|
|
|
portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, related_name='transactions')
|
|
action = models.CharField(max_length=4, choices=ACTION_CHOICES)
|
|
stock_code = models.CharField(max_length=20, help_text="Stock ticker code, e.g., 'NVDA', '9988.HK'")
|
|
quantity = models.DecimalField(
|
|
max_digits=20,
|
|
decimal_places=6,
|
|
validators=[MinValueValidator(Decimal('0.000001'))],
|
|
help_text="Number of shares"
|
|
)
|
|
price_per_share = models.DecimalField(
|
|
max_digits=20,
|
|
decimal_places=6,
|
|
validators=[MinValueValidator(Decimal('0'))],
|
|
help_text="Price per share at time of transaction"
|
|
)
|
|
date = models.DateField()
|
|
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = ['-date', '-created_at']
|
|
|
|
def __str__(self):
|
|
return f"{self.action} {self.quantity} {self.stock_code} @ {self.price_per_share} on {self.date}"
|