Files
fxhnt/tests/integration/test_forward_ingest.py
jgrusewski d0d84497c7 chore(surfer): cockpit cleanup — retire dead legacy tracks + fix seed-registry prune bug
Prune the dead/superseded paper tracks: multistrat + gd (futures/TradFi premia — falsified
this session, scale-gated, no deployable edge) + poc (old crypto residual-mom+VRP PoC,
superseded by the two validated edges). Strategy classes stay in paper_strategies.py (shelf).
Removed their assets, registry entries, job/Definitions membership, cockpit_forward deps.

ROOT-CAUSE FIX: _seed_registry() now PRUNES strategy_registry rows absent from the Python
registry — previously it merge-upserted but never deleted, so retired tracks lingered on the
dashboard forever (the stale-funding bug). Retirements now stick automatically.

Fleet now 10 assets / 6 tracks: 3 crypto edges (combined, xsfunding, unlock) + 2 equity-factor
sleeves + 60/40 benchmark. Ingest is registry-driven so leftover state files are safely ignored
(no nightly-run crash risk). Tests updated; full suite 511 passed, mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 22:27:19 +02:00

52 lines
2.1 KiB
Python

"""Ingest walks the registry, reads each present state file, computes the gate, and upserts rows + summary.
A missing or malformed state file is skipped (logged), never aborts the batch."""
from __future__ import annotations
import datetime as dt
import json
from fxhnt.adapters.persistence.forward_nav import ForwardNavRepo
from fxhnt.application.forward_ingest import ForwardIngestService
def _setup(tmp_path):
(tmp_path / "fxhnt_combined_forward.json").write_text(json.dumps({
"inception": "2026-06-04", "last_date": "2026-06-06", "nav": 1.0201,
"days": [{"date": "2026-06-05", "ret": 0.01, "nav": 1.01},
{"date": "2026-06-06", "ret": 0.0099, "nav": 1.0201}],
}))
(tmp_path / "sixtyforty_state.json").write_text(json.dumps({
"last_date": "2026-06-12", "days": 5, "sum_r": -0.0007, "sumsq_r": 1.88e-05,
"equity": 0.99926, "peak": 1.0014, "max_dd": -0.0046,
}))
repo = ForwardNavRepo("sqlite://")
repo.migrate()
return repo
def test_ingest_populates_summaries_and_rows(tmp_path) -> None:
repo = _setup(tmp_path)
svc = ForwardIngestService(repo, str(tmp_path))
n = svc.ingest(at=dt.datetime(2026, 6, 14, 23, 30))
assert n == 2 # two present trackers ingested
summaries = {r.strategy_id: r for r in repo.all_summaries()}
assert "combined" in summaries and "sixtyforty" in summaries
assert summaries["combined"].gate_status == "WAIT" # 2 < 20 days
assert len(repo.nav_history("combined")) == 2
def test_ingest_skips_missing_files(tmp_path) -> None:
repo = _setup(tmp_path)
(tmp_path / "sixtyforty_state.json").unlink() # now only combined present
svc = ForwardIngestService(repo, str(tmp_path))
n = svc.ingest(at=dt.datetime(2026, 6, 14, 23, 30))
assert n == 1
def test_ingest_skips_malformed_file(tmp_path) -> None:
repo = _setup(tmp_path)
(tmp_path / "sixtyforty_state.json").write_text("{ not json")
svc = ForwardIngestService(repo, str(tmp_path))
n = svc.ingest(at=dt.datetime(2026, 6, 14, 23, 30)) # malformed skipped, combined still ingested
assert n == 1