Files
finance-talk/ft-app/app/seed.py
T

118 lines
4.5 KiB
Python

"""Seed database from existing data files. Run once manually or on first start."""
from datetime import date
from app.database import engine, Base, SessionLocal
from app.models import DailyBar, Product, Contract, User
from app.engine.lock_strategy import compute_amp_5d
# --- Seed OHLCV data ---
SEED_CONTRACT = "FG2609"
SEED_BARS: list[dict] = [
{"date": "2026-07-01", "open": 972, "close": 961, "high": 972, "low": 956},
{"date": "2026-07-02", "open": 960, "close": 966, "high": 972, "low": 957},
{"date": "2026-07-03", "open": 965, "close": 973, "high": 979, "low": 962},
{"date": "2026-07-06", "open": 977, "close": 967, "high": 982, "low": 964},
{"date": "2026-07-07", "open": 966, "close": 952, "high": 966, "low": 951},
{"date": "2026-07-08", "open": 954, "close": 962, "high": 966, "low": 951},
{"date": "2026-07-09", "open": 963, "close": 957, "high": 964, "low": 949},
{"date": "2026-07-10", "open": 956, "close": 965, "high": 974, "low": 952},
{"date": "2026-07-13", "open": 965, "close": 952, "high": 967, "low": 950},
{"date": "2026-07-14", "open": 954, "close": 951, "high": 956, "low": 944},
{"date": "2026-07-15", "open": 950, "close": 949, "high": 958, "low": 944},
{"date": "2026-07-16", "open": 949, "close": 929, "high": 952, "low": 927},
{"date": "2026-07-17", "open": 931, "close": 900, "high": 931, "low": 899},
{"date": "2026-07-20", "open": 902, "close": 890, "high": 908, "low": 889},
{"date": "2026-07-21", "open": 891, "close": 904, "high": 910, "low": 891},
{"date": "2026-07-22", "open": 908, "close": 913, "high": 918, "low": 900},
{"date": "2026-07-23", "open": 914, "close": 899, "high": 917, "low": 892},
{"date": "2026-07-24", "open": 900, "close": 908, "high": 912, "low": 891},
]
def _migrate(engine):
"""Add missing columns to existing tables (SQLite doesn't auto-migrate)."""
import sqlite3
conn = engine.raw_connection()
try:
cur = conn.cursor()
cur.execute("PRAGMA table_info(rounds)")
cols = {row[1] for row in cur.fetchall()}
if "max_locks" not in cols:
cur.execute("ALTER TABLE rounds ADD COLUMN max_locks INTEGER DEFAULT 3")
conn.commit()
finally:
conn.close()
def seed():
Base.metadata.create_all(bind=engine)
_migrate(engine)
db = SessionLocal()
try:
# --- Seed default user ---
if not db.query(User).first():
admin = User(
username="admin",
password_hash=User.hash_password("admin123"),
role="admin",
)
db.add(admin)
db.flush()
# --- Seed products and contracts ---
if not db.query(Product).first():
fg = Product(code="FG", name="玻璃", exchange="CZCE")
db.add(fg)
db.flush()
db.add_all([
Contract(product_id=fg.id, code="FG2609", name="玻璃2609", is_active=True),
Contract(product_id=fg.id, code="FG2610", name="玻璃2610", is_active=True),
Contract(product_id=fg.id, code="FG2611", name="玻璃2611", is_active=True),
Contract(product_id=fg.id, code="FG2701", name="玻璃2701", is_active=True),
])
# --- Seed daily bars ---
existing_dates = {
(r.contract, r.date)
for r in db.query(DailyBar.contract, DailyBar.date).all()
}
bars_to_insert = []
for bar in SEED_BARS:
d = date.fromisoformat(bar["date"])
if (SEED_CONTRACT, d) not in existing_dates:
bars_to_insert.append(
DailyBar(
contract=SEED_CONTRACT,
date=d,
open=bar["open"],
close=bar["close"],
high=bar["high"],
low=bar["low"],
)
)
if bars_to_insert:
db.add_all(bars_to_insert)
db.flush()
# Compute amp_5d
seed_bars = (
db.query(DailyBar)
.filter(DailyBar.contract == SEED_CONTRACT)
.order_by(DailyBar.date)
.all()
)
for i, bar in enumerate(seed_bars):
if i >= 5:
bar.amp_5d = compute_amp_5d([b.diff for b in seed_bars[i - 5 : i]])
db.commit()
print(f"Seeded {len(bars_to_insert)} bars")
finally:
db.close()
if __name__ == "__main__":
seed()