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>
182 lines
5.5 KiB
Python
182 lines
5.5 KiB
Python
#!/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()
|