Task 6+7 (shipped together per plan so the key is never gone while a literal still references it). Registry: 12->10 keys (vrp/vrp_exec removed). Literals: _IBKR_ACCOUNT_SIDS + SIM_BOOKS + _REF_ALIAS drop vrp. Tests that asserted vrp-present updated to assert vrp-ABSENT. Covering tests (forward_health, dashboard_service, forward_definition, sim_curves, display_names) 39 green: surviving strategies still WAIT-by-default (Constraint 2 upheld). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
75 lines
4.0 KiB
Python
75 lines
4.0 KiB
Python
from fxhnt.application.forward_definition import definition_hash, inception_override, track_definition
|
|
from fxhnt.registry import STRATEGY_REGISTRY
|
|
|
|
|
|
def test_hash_is_stable_under_key_reordering():
|
|
assert definition_hash({"a": 1, "b": 2}, 1) == definition_hash({"b": 2, "a": 1}, 1)
|
|
|
|
|
|
def test_hash_changes_when_a_param_changes():
|
|
# the BTC-drop case: instruments 6 -> 5 must change the hash
|
|
six = definition_hash({"instruments": ["SPY", "IEF", "GLD", "PDBC", "DBMF", "BTC-USD"]}, 1)
|
|
five = definition_hash({"instruments": ["SPY", "IEF", "GLD", "PDBC", "DBMF"]}, 1)
|
|
assert six != five
|
|
|
|
|
|
def test_hash_changes_when_version_bumps():
|
|
assert definition_hash({"a": 1}, 1) != definition_hash({"a": 1}, 2)
|
|
|
|
|
|
def test_every_active_track_declares_a_definition():
|
|
for sid in STRATEGY_REGISTRY:
|
|
params, version, mode = track_definition(sid)
|
|
assert isinstance(params, dict) and isinstance(version, int)
|
|
assert mode in ("recompute", "observed")
|
|
|
|
|
|
def test_observed_mode_is_exactly_the_executed_twins():
|
|
# Pin is deliberately exhaustive: whenever a new track adopts record_mode="observed", update this set
|
|
# (C2 Task 3 added bybit_4edge_exec) so the change is reviewed, not silently absorbed. `xsfunding` moved
|
|
# OFF observed (Phase 0b venue consolidation: standalone Binance `XsFundingForward` -> its own Bybit
|
|
# single-sleeve `recompute` track, mirroring `positioning`) — the remaining observed tracks are the
|
|
# OBSERVED-fills executed twins (fills are observed, not recomputable).
|
|
observed = {sid for sid in STRATEGY_REGISTRY if track_definition(sid)[2] == "observed"}
|
|
assert observed == {"multistrat_exec", "bybit_4edge_exec"}
|
|
|
|
|
|
def test_inception_override_returns_date_when_version_matches(monkeypatch):
|
|
monkeypatch.setitem(STRATEGY_REGISTRY, "t_ov",
|
|
{"definition": {"params": {"v": 1}, "version": 2, "record_mode": "recompute",
|
|
"inception_t0": {"date": "2026-06-20", "version": 2}}})
|
|
assert inception_override("t_ov") == "2026-06-20"
|
|
|
|
|
|
def test_inception_override_ignored_when_version_stale(monkeypatch):
|
|
# a genuine re-tune bumped the definition to v3 but left the v2 override → stale → ignored (fresh clock)
|
|
monkeypatch.setitem(STRATEGY_REGISTRY, "t_ov",
|
|
{"definition": {"params": {"v": 3}, "version": 3, "record_mode": "recompute",
|
|
"inception_t0": {"date": "2026-06-20", "version": 2}}})
|
|
assert inception_override("t_ov") is None
|
|
|
|
|
|
def test_inception_override_absent_returns_none(monkeypatch):
|
|
monkeypatch.setitem(STRATEGY_REGISTRY, "t_ov",
|
|
{"definition": {"params": {"v": 1}, "version": 1, "record_mode": "recompute"}})
|
|
assert inception_override("t_ov") is None
|
|
|
|
|
|
def test_inception_t0_is_not_hashed():
|
|
# the recovered-window pin MUST live outside `params` — else declaring it would change the definition hash
|
|
# and itself re-incept the live anchor, resetting the OOS clock (the exact opposite of its purpose).
|
|
for sid in ("xsfunding", "unlock", "positioning", "bybit_4edge", "bybit_4edge_levered"):
|
|
assert "inception_t0" not in track_definition(sid)[0]
|
|
|
|
|
|
def test_re_homed_sleeves_pin_their_recovered_inception():
|
|
# Regression: the Phase-0b faithful re-homes keep their pinned pre-re-home OOS start (recovered 2026-07-15)
|
|
# so a DB rebuild reproduces the window from git instead of restarting at today. If a sleeve is genuinely
|
|
# re-tuned later, its version bumps and the (now version-stale) pin is correctly ignored — update it here.
|
|
# 2026-07-20: positioning coin_gross_cap=0.07 re-inception (v3) backdated bybit_4edge/bybit_4edge_levered's
|
|
# pin from 2026-07-07 to 2026-07-06 (positioning's date, unchanged) so the whole book re-warms together.
|
|
expected = {"xsfunding": "2026-07-07", "unlock": "2026-06-20", "positioning": "2026-07-06",
|
|
"bybit_4edge": "2026-07-06", "bybit_4edge_levered": "2026-07-06"}
|
|
for sid, date in expected.items():
|
|
assert inception_override(sid) == date
|