feat: generate transaction records from snapshot diffs in seed script
All checks were successful
Deploy to Production / deploy (push) Successful in 1m27s
All checks were successful
Deploy to Production / deploy (push) Successful in 1m27s
Derive buy/sell transactions by comparing consecutive snapshots and replace existing portfolio on re-run instead of skipping.
This commit is contained in:
parent
48417a03f5
commit
a899c17a65
@ -8,7 +8,7 @@ Requires: DATABASE_URL environment variable or default dev connection.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
from datetime import date
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
|
||||
# Add backend to path
|
||||
@ -19,6 +19,7 @@ from app.core.database import SessionLocal
|
||||
from app.models.portfolio import (
|
||||
Portfolio, PortfolioType, Target, Holding,
|
||||
PortfolioSnapshot, SnapshotHolding,
|
||||
Transaction, TransactionType,
|
||||
)
|
||||
from app.models.user import User
|
||||
|
||||
@ -131,6 +132,17 @@ SNAPSHOTS = [
|
||||
{"ticker": "411060", "qty": 328, "price": Decimal("29605"), "value": Decimal("9710440")},
|
||||
],
|
||||
},
|
||||
{
|
||||
"date": date(2026, 2, 16),
|
||||
"total_assets": Decimal("62433665"),
|
||||
"holdings": [
|
||||
{"ticker": "069500", "qty": 16, "price": Decimal("81835"), "value": Decimal("1309360")},
|
||||
{"ticker": "148070", "qty": 133, "price": Decimal("108290"), "value": Decimal("14402570")},
|
||||
{"ticker": "284430", "qty": 1386, "price": Decimal("19250"), "value": Decimal("26680500")},
|
||||
{"ticker": "360750", "qty": 385, "price": Decimal("24435"), "value": Decimal("9407475")},
|
||||
{"ticker": "411060", "qty": 328, "price": Decimal("32420"), "value": Decimal("10633760")},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@ -142,14 +154,15 @@ def seed(db: Session):
|
||||
print("ERROR: No user found in database. Create a user first.")
|
||||
return
|
||||
|
||||
# Check if portfolio already exists
|
||||
# Delete existing portfolio if present (cascade deletes related records)
|
||||
existing = db.query(Portfolio).filter(
|
||||
Portfolio.user_id == user.id,
|
||||
Portfolio.name == "연금 포트폴리오",
|
||||
).first()
|
||||
if existing:
|
||||
print(f"Portfolio '연금 포트폴리오' already exists (id={existing.id}). Skipping.")
|
||||
return
|
||||
db.delete(existing)
|
||||
db.flush()
|
||||
print(f"Deleted existing portfolio (id={existing.id})")
|
||||
|
||||
# Create portfolio
|
||||
portfolio = Portfolio(
|
||||
@ -189,6 +202,45 @@ def seed(db: Session):
|
||||
))
|
||||
print(f" Snapshot {snap['date']}: {len(snap['holdings'])} holdings")
|
||||
|
||||
# Create transactions by comparing consecutive snapshots
|
||||
tx_count = 0
|
||||
for i, snap in enumerate(SNAPSHOTS):
|
||||
current_holdings = {h["ticker"]: h for h in snap["holdings"]}
|
||||
|
||||
if i == 0:
|
||||
# First snapshot: all holdings are initial buys
|
||||
prev_holdings = {}
|
||||
else:
|
||||
prev_holdings = {h["ticker"]: h for h in SNAPSHOTS[i - 1]["holdings"]}
|
||||
|
||||
all_tickers = set(current_holdings.keys()) | set(prev_holdings.keys())
|
||||
for ticker in all_tickers:
|
||||
cur_qty = current_holdings[ticker]["qty"] if ticker in current_holdings else 0
|
||||
prev_qty = prev_holdings[ticker]["qty"] if ticker in prev_holdings else 0
|
||||
diff = cur_qty - prev_qty
|
||||
|
||||
if diff == 0:
|
||||
continue
|
||||
|
||||
if diff > 0:
|
||||
tx_type = TransactionType.BUY
|
||||
price = current_holdings[ticker]["price"]
|
||||
else:
|
||||
tx_type = TransactionType.SELL
|
||||
price = prev_holdings[ticker]["price"]
|
||||
|
||||
db.add(Transaction(
|
||||
portfolio_id=portfolio.id,
|
||||
ticker=ticker,
|
||||
tx_type=tx_type,
|
||||
quantity=abs(diff),
|
||||
price=price,
|
||||
executed_at=datetime.combine(snap["date"], datetime.min.time()),
|
||||
))
|
||||
tx_count += 1
|
||||
|
||||
print(f"Created {tx_count} transactions from snapshot diffs")
|
||||
|
||||
# Set current holdings from latest snapshot
|
||||
latest = SNAPSHOTS[-1]
|
||||
for h in latest["holdings"]:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user