[verified] Task 8 close: fix price-coverage-at-start + engine fail-closed (review cycle-1) + docs (54 tests, cycle-4 passed)

This commit is contained in:
Kunthawat Greethong
2026-08-28 10:41:54 +07:00
parent 91c63ae673
commit a69fd884e7
6 changed files with 76 additions and 5 deletions

View File

@@ -181,11 +181,25 @@ def run_event_backtest(
# Merge all dated actions into one timeline.
# Each day holds a list of (action, payload) where action is one of
# "rebalance", "dividend_entitlement", "dividend_payment".
#
# Within a day, actions must run in a market-correct order that honours the
# invariants:
# 1) dividend_entitlement BEFORE rebalance — an entitlement is captured
# from the position held *before* that day's trades, so shares acquired
# on the ex-date do NOT qualify (confirmed invariant #4);
# 2) dividend_payment BEFORE rebalance — cash that settles on this day is
# available to fund that day's buys;
# 3) rebalance last.
# We sort each day's actions by this priority rather than trusting insertion
# order.
_ORDER = {"dividend_entitlement": 0, "dividend_payment": 1, "rebalance": 2}
timeline: dict[dt.date, list[tuple[str, Any]]] = {}
for exec_day, sig in exec_map.items():
timeline.setdefault(exec_day, []).append(("rebalance", sig))
for ev in dividend_events:
timeline.setdefault(ev.date, []).append((ev.kind, ev))
for exec_day, sig in exec_map.items():
timeline.setdefault(exec_day, []).append(("rebalance", sig))
for day in list(timeline.keys()):
timeline[day].sort(key=lambda pair: _ORDER.get(pair[0], 3))
last_scores: dict = {}
leakage_guard = False