chore(cockpit): local demo seed for browser verification of the surfacing
Adds seed_cockpit_demo.py script to populate the cockpit database with representative forward track data (4 strategies), nav histories, backtest summaries, and allocation/funding snapshots. Idempotent — safe to re-run multiple times. Supports env override FXHNT_OPERATIONAL_DSN (defaults to sqlite:///./cockpit-demo.db). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
181
scripts/seed_cockpit_demo.py
Normal file
181
scripts/seed_cockpit_demo.py
Normal file
@@ -0,0 +1,181 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Seed the cockpit demo database with representative forward track and allocation/funding data.
|
||||
|
||||
Usage:
|
||||
export FXHNT_OPERATIONAL_DSN="sqlite:///./cockpit-demo.db"
|
||||
python scripts/seed_cockpit_demo.py
|
||||
|
||||
The script creates a fresh schema and seeds 4 strategies with forward summaries, nav histories,
|
||||
a backtest summary, and allocation/funding snapshots. Fully idempotent — safe to re-run.
|
||||
"""
|
||||
import datetime as dt
|
||||
import os
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from fxhnt.adapters.persistence.cockpit_models import (
|
||||
BacktestSummaryRow,
|
||||
ForwardNavRow,
|
||||
ForwardSummaryRow,
|
||||
StrategyAllocationRow,
|
||||
StrategyFundingRow,
|
||||
)
|
||||
from fxhnt.adapters.persistence.forward_nav import ForwardNavRepo
|
||||
|
||||
|
||||
def seed_cockpit_demo() -> None:
|
||||
dsn = os.getenv("FXHNT_OPERATIONAL_DSN", "sqlite:///./cockpit-demo.db")
|
||||
|
||||
repo = ForwardNavRepo(dsn)
|
||||
repo.migrate()
|
||||
|
||||
at = dt.datetime(2026, 7, 10, 10, 0, 0)
|
||||
|
||||
# Idempotent: delete existing summaries and nav rows to avoid duplication on re-runs
|
||||
with Session(repo._engine) as s:
|
||||
s.query(ForwardSummaryRow).delete()
|
||||
s.query(ForwardNavRow).delete()
|
||||
s.query(BacktestSummaryRow).delete()
|
||||
s.commit()
|
||||
|
||||
# Seed forward summaries (4 strategies) and their nav histories
|
||||
strategies = [
|
||||
("bybit_4edge", 0.0031, 2),
|
||||
("bybit_4edge_exec", 0.0019, 2),
|
||||
("multistrat", 0.012, 1),
|
||||
("positioning", 0.02, 2),
|
||||
]
|
||||
|
||||
with Session(repo._engine) as s:
|
||||
for strategy_id, total_return, days in strategies:
|
||||
summary = ForwardSummaryRow(
|
||||
strategy_id=strategy_id,
|
||||
as_of="2026-07-10",
|
||||
days=days,
|
||||
nav=1.0 + total_return,
|
||||
total_return=total_return,
|
||||
sharpe=1.0,
|
||||
maxdd=-0.05,
|
||||
gate_status="WAIT",
|
||||
gate_reason="",
|
||||
src_updated_at=at,
|
||||
)
|
||||
s.add(summary)
|
||||
|
||||
s.commit()
|
||||
|
||||
# Seed nav histories (5-day ascending series for each strategy)
|
||||
nav_start = dt.date(2026, 7, 6)
|
||||
with Session(repo._engine) as s:
|
||||
for strategy_id, total_return, _ in strategies:
|
||||
# Build a 5-day nav series ascending to the final nav value
|
||||
nav_step = total_return / 5
|
||||
for i in range(5):
|
||||
nav_val = 1.0 + (nav_step * (i + 1))
|
||||
ret_val = nav_step
|
||||
s.add(
|
||||
ForwardNavRow(
|
||||
strategy_id=strategy_id,
|
||||
date=nav_start + dt.timedelta(days=i),
|
||||
ret=ret_val,
|
||||
nav=nav_val,
|
||||
src_updated_at=at,
|
||||
)
|
||||
)
|
||||
s.commit()
|
||||
|
||||
# Seed backtest summary for bybit_4edge
|
||||
with Session(repo._engine) as s:
|
||||
backtest = BacktestSummaryRow(
|
||||
strategy_id="bybit_4edge",
|
||||
as_of="2026-07-10",
|
||||
cagr=0.318,
|
||||
ann_vol=0.12,
|
||||
sharpe=2.20,
|
||||
max_drawdown=-0.08,
|
||||
passed=True,
|
||||
dsr=0.98,
|
||||
is_sharpe=2.15,
|
||||
oos_sharpe=1.95,
|
||||
pvalue=0.001,
|
||||
src_updated_at=at,
|
||||
)
|
||||
s.add(backtest)
|
||||
s.commit()
|
||||
|
||||
# Seed allocations: bybit_4edge ($18,900 / 54%) and positioning ($9,500 / 27%)
|
||||
repo.replace_allocations(
|
||||
[
|
||||
StrategyAllocationRow(
|
||||
strategy_id="bybit_4edge",
|
||||
target_weight=0.54,
|
||||
target_dollars=18900.0,
|
||||
policy_version=1,
|
||||
policy_hash="h",
|
||||
as_of="2026-07-10",
|
||||
computed_at=at,
|
||||
),
|
||||
StrategyAllocationRow(
|
||||
strategy_id="positioning",
|
||||
target_weight=0.27,
|
||||
target_dollars=9500.0,
|
||||
policy_version=1,
|
||||
policy_hash="h",
|
||||
as_of="2026-07-10",
|
||||
computed_at=at,
|
||||
),
|
||||
],
|
||||
at,
|
||||
)
|
||||
|
||||
# Seed funding: bybit_4edge (funded), positioning (decaying), multistrat (de-funded)
|
||||
repo.replace_funding(
|
||||
[
|
||||
StrategyFundingRow(
|
||||
strategy_id="bybit_4edge",
|
||||
state="funded",
|
||||
label="funded",
|
||||
decay_run=0,
|
||||
recovery_run=0,
|
||||
first_pass_date=None,
|
||||
policy_version=2,
|
||||
policy_hash="h",
|
||||
as_of="2026-07-10",
|
||||
computed_at=at,
|
||||
),
|
||||
StrategyFundingRow(
|
||||
strategy_id="positioning",
|
||||
state="funded",
|
||||
label="decaying",
|
||||
decay_run=4,
|
||||
recovery_run=0,
|
||||
first_pass_date=None,
|
||||
policy_version=2,
|
||||
policy_hash="h",
|
||||
as_of="2026-07-10",
|
||||
computed_at=at,
|
||||
),
|
||||
StrategyFundingRow(
|
||||
strategy_id="multistrat",
|
||||
state="de-funded",
|
||||
label="de-funded",
|
||||
decay_run=0,
|
||||
recovery_run=0,
|
||||
first_pass_date="2026-06-20",
|
||||
policy_version=2,
|
||||
policy_hash="h",
|
||||
as_of="2026-07-10",
|
||||
computed_at=at,
|
||||
),
|
||||
],
|
||||
at,
|
||||
)
|
||||
|
||||
print(f"Seeded cockpit demo: {dsn}")
|
||||
print(
|
||||
f"Run: export FXHNT_OPERATIONAL_DSN='{dsn}' && python scripts/dev_cockpit_local.py"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
seed_cockpit_demo()
|
||||
Reference in New Issue
Block a user