Files
fxhnt/tests/unit/test_forward_definition.py
jgrusewski 595dc5da0e feat(forward): pin re-homed sleeves' recovered OOS inception in git (reproducible on DB rebuild)
The Phase-0b venue re-home reset the crypto sleeves' forward OOS clock to 2026-07-14
(definition-hash change → auto-re-inception). Since these were faithful re-homes (same
edge + PIT data, record_mode=recompute), the pre-re-home days are still valid OOS; on
2026-07-15 they were recovered by backdating the active anchors' t0 in the DB (unlock
06-20 → recon-gate PASS +4.57%; xsfunding/positioning/bybit_4edge/levered → 8d).

That backdate lived ONLY in the DB — a full operational-Postgres rebuild would let the
anchors re-incept to `today` and silently lose the recovered window. This makes it
reproducible from git (the SSOT):

- forward_definition.inception_override(sid): returns a definition's declared
  `inception_t0.date`, VERSION-PINNED (honored only when its `version` == the
  definition's current version — a genuine re-tune bumps `version`, auto-ignoring a
  stale pin and correctly getting a fresh today-clock). Lives OUTSIDE `params` so it is
  NOT hashed — declaring it never itself re-inceptions (verified: the five sleeves'
  definition_hash is byte-identical to their live DB anchors).
- run_track: at inception, t0 = inception_override(sid) if present AND <= today, else
  today (never incept in the future — clock-skew/not-yet-reached pins fall back to today).
- registry: xsfunding/unlock/positioning/bybit_4edge/bybit_4edge_levered carry their
  pinned pre-re-home t0 (07-07/06-20/07-06/07-07/07-07, version 2).

Tests: inception_override version match/stale/absent + not-hashed + a regression pin on
the recovered dates; run_track honors the pin, ignores a version-stale pin, and falls
back to today for a future pin. 262 forward/registry tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:31:16 +02:00

73 lines
3.8 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; Task 7 added vrp_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", "vrp_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.
expected = {"xsfunding": "2026-07-07", "unlock": "2026-06-20", "positioning": "2026-07-06",
"bybit_4edge": "2026-07-07", "bybit_4edge_levered": "2026-07-07"}
for sid, date in expected.items():
assert inception_override(sid) == date