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 sys
|
||||||
import os
|
import os
|
||||||
from datetime import date
|
from datetime import date, datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
# Add backend to path
|
# Add backend to path
|
||||||
@ -19,6 +19,7 @@ from app.core.database import SessionLocal
|
|||||||
from app.models.portfolio import (
|
from app.models.portfolio import (
|
||||||
Portfolio, PortfolioType, Target, Holding,
|
Portfolio, PortfolioType, Target, Holding,
|
||||||
PortfolioSnapshot, SnapshotHolding,
|
PortfolioSnapshot, SnapshotHolding,
|
||||||
|
Transaction, TransactionType,
|
||||||
)
|
)
|
||||||
from app.models.user import User
|
from app.models.user import User
|
||||||
|
|
||||||
@ -131,6 +132,17 @@ SNAPSHOTS = [
|
|||||||
{"ticker": "411060", "qty": 328, "price": Decimal("29605"), "value": Decimal("9710440")},
|
{"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.")
|
print("ERROR: No user found in database. Create a user first.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if portfolio already exists
|
# Delete existing portfolio if present (cascade deletes related records)
|
||||||
existing = db.query(Portfolio).filter(
|
existing = db.query(Portfolio).filter(
|
||||||
Portfolio.user_id == user.id,
|
Portfolio.user_id == user.id,
|
||||||
Portfolio.name == "연금 포트폴리오",
|
Portfolio.name == "연금 포트폴리오",
|
||||||
).first()
|
).first()
|
||||||
if existing:
|
if existing:
|
||||||
print(f"Portfolio '연금 포트폴리오' already exists (id={existing.id}). Skipping.")
|
db.delete(existing)
|
||||||
return
|
db.flush()
|
||||||
|
print(f"Deleted existing portfolio (id={existing.id})")
|
||||||
|
|
||||||
# Create portfolio
|
# Create portfolio
|
||||||
portfolio = Portfolio(
|
portfolio = Portfolio(
|
||||||
@ -189,6 +202,45 @@ def seed(db: Session):
|
|||||||
))
|
))
|
||||||
print(f" Snapshot {snap['date']}: {len(snap['holdings'])} holdings")
|
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
|
# Set current holdings from latest snapshot
|
||||||
latest = SNAPSHOTS[-1]
|
latest = SNAPSHOTS[-1]
|
||||||
for h in latest["holdings"]:
|
for h in latest["holdings"]:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user