SniperGold_ML/docs/P3_S_F7_EVENT_LIFECYCLE_FORENSIC.md

238 lines
9.9 KiB
Markdown
Raw Permalink Normal View History

# P3-S.0 F7 EVENT LIFECYCLE FORENSIC — LIQUIDITY GRAB STATE/EVENT BUG REPAIR
```text
Date : 2026-08-22
Session : P3-S.0 — SAFE SEMANTIC BUG REPAIR (f7 DetectLiquidityGrabs)
Scope : ONLY the f7 event lifecycle. f10/f11, OB, FVG, CHoCH, timeframe, ML UNCHANGED.
Checkpoint : b877fb6 (P3 Golden Dataset Phase 1) — working tree clean at start
Provenance : P2 8d330343 | contract C44CC6F2 | model 06df8452 | dataset e85a0861
```
---
## A. ORIGINAL BEHAVIOR
`DetectLiquidityGrabs` (f7 sweep_dir) — FEATURE_CONTRACT v1.0:
```text
reference : internal swing pivot (fractal len=5)
trigger condition: bearish grab: isHigh && high[b]>lvl && close[b]<lvl (buy-side swept -> -1)
bullish grab: !isHigh && low[b]<lvl && close[b]>lvl (sell-side swept -> +1)
detect window : 8 bars after the pivot (GRAB_WINDOW)
state variables : g_swpDir, g_swpBar, g_swpLevel
reset : g_swpDir=0; g_swpBar=-1 at the START of every bar (ComputeAll)
expiration : NONE
emission : g_feat[7] = g_swpDir (raw, no age bound)
consumption : f9 (chochOK) uses g_swpBar/g_swpDir; f18 (+15); E_BUY/E_SELL stream
```
Measured behavior (XAUUSD M15, 2017-2026, n=197.032):
```text
onsets = 2.835
active bars = 196.928 (99,95%)
repetition ratio = 69,5x
state run median = 94 bars
state run max = 996 bars
NEVER resets to 0 after the first grab
```
## B. ROOT CAUSE
```text
1. The LEGACY state is "last-grab-ever": every bar, ComputeAll resets g_swpDir=0,
then DetectLiquidityGrabs scans ALL internal pivots (700-bar window) and fills
g_swpDir = the direction of the MOST RECENT grab ever — including grabs long past
(filtered only by the pivot window [t-649, t-50], not by event age).
2. No expiration: g_feat[7] = g_swpDir is emitted without checking
(current_bar - g_swpBar). Consequently a single onset yields TRUE for hundreds of bars.
3. Event consumers (f9-confirm stream E_BUY/E_SELL) treat the state as a repeated event
-> P3.2.2: retention 1.5%, cluster 46 bars, serial dependence disappears only after de-overlap.
NOT a bug in the trigger condition (wick/close-back/8-bar window) — that was NOT changed.
```
## C. WHY IT IS A BUG
```text
Intended semantics (FEATURE_CONTRACT f7): "direction of the LAST liquidity grab (internal pivot)".
As an EVENT feature, a single onset must NOT produce TRUE for hundreds of bars.
Legacy behavior = persistent state counted as an event -> redundant event stream,
not independent (ac1 0.50 in ALL, see P3.2.2), invalid setup units.
Standard event lifecycle:
NO_SWEEP -> SWEEP_ONSET -> EVENT_CONSUMED/EXPIRED -> NO_SWEEP
```
## D. CORRECTED EVENT LIFECYCLE
```text
Expiration derived from semantics ALREADY present in the implementation (not arbitrary):
InpSeqWindow = 40 (v4.4/v4.5): "Max bars: sweep -> CHoCH -> entry must chain within".
v4.4/v4.5 already use (curBar - g_swpBar) <= InpSeqWindow for the sweepBull/Bear signal gate.
f7 fix:
f7[r] = g_swpDir[r] if g_swpBar[r] >= 0 AND (r - g_swpBar[r]) <= SEQ_WINDOW (40)
0 if expired (age > 40) / no grab
Resulting lifecycle:
NO_SWEEP (0) -> SWEEP_ONSET (dir) -> valid up to onset+40 bars -> EXPIRED -> NO_SWEEP (0)
A newer event (more recent grab) replaces the old event (existing semantics: b > g_swpBar).
An event arriving within the 40-bar window "refreshes" (chain) — not one onset producing
hundreds of bars, but several sequential onsets.
UNCHANGED:
- trigger condition (wick + close-back), GRAB_WINDOW=8, pivot len=5
- internal g_swpDir/g_swpBar (used by f9/f18) — remains legacy state
- f10/f11, OB, FVG, CHoCH, M15 timeframe, ML
```
## E. CODE CHANGE
### E.1 EA runtime — `Experts\AlgoForge_Backtest_Baseline.mq5` (root & publish)
```mql5
// new (after AF_BT_GRAB_WIN):
#define AF_BT_SEQ_WINDOW 40 // InpSeqWindow (v4.4): sweep -> CHoCH -> entry chain window
// = event validity/expiry for f7 (P3-S.0 f7 event lifecycle fix)
// replace g_feat[7] = g_swpDir; ->
// P3-S.0 f7 event lifecycle fix: sweep_dir is active only during the valid event
// (onset .. onset+SeqWindow); after expiry -> NO_SWEEP (0). Does not change the
// trigger condition/close-back/pivot; internal g_swpDir stays for f9/f18.
g_feat[7] =(g_swpBar>=0 && (tc-1-g_swpBar)<=AF_BT_SEQ_WINDOW)? g_swpDir : 0; // sweep_dir
```
### E.2 Indicator v4.4 — `SniperGold_SMC_ProPlus_v4_4.mq5`
```mql5
g_feat[7] =(g_swpBar>=0 && (tc-1-g_swpBar)<=InpSeqWindow)? g_swpDir : 0; // sweep_dir
```
### E.3 Indicator v4.5 — `SniperGold_SMC_ProPlus_v4_5.mq5`
```mql5
g_feat[6]=eqPos; g_feat[7]=((g_swpBar>=0 && (tc-1-g_swpBar)<=InpSeqWindow)? g_swpDir : 0); g_feat[8]=g_chochDir;
```
### E.4 Python machine annotator — `ml/p3/smc_semantic/`
```text
smc_semantic_common.py : + SEQ_WINDOW=40 ; + f7_lifecycle(sweep_dir, sweep_bar)
machine_annotator.py : v2 uses f7_lifecycle; output machine_annotations_f7_v2.csv
```
Compile: EA 0 errors / v4.4 0 errors / v4.5 0 errors (MetaEditor, build 6093, AVX512).
## F. REGRESSION TESTS
File: `ml/p3/smc_semantic/test_f7_lifecycle.py`**15/15 PASS**
```text
R1 Single onset : 1 event (not multiple) PASS
R1 active bounded : active_bars <= 41 PASS
R2 Persistent condition : condition true 450 bars -> 1 event PASS
R3 New independent sweep : 2 separate events PASS
R4 Invalidated/expired : f7[100]=0 (age>40), f7[10]=1 PASS
R5 No-sweep : 0 events PASS
R6 f10 unchanged vs cache : 0 mismatch / 4000 bars PASS
R6 f11 unchanged vs cache : 0 mismatch / 4000 bars PASS
R6 EA source contains fix : AF_BT_SEQ_WINDOW + (tc-1-g_swpBar)<=... PASS
R6 v4.4 / v4.5 contain fix : PASS PASS
R6 compile : EA/v4.4/v4.5 0 errors 0 warnings (manual) PASS
```
## G. BEFORE / AFTER HISTORICAL RESULTS
```text
METRIC BEFORE AFTER
onsets 2.835 2.835 (trigger unchanged)
active bars f7 != 0 196.928 90.140
% active bars 99,95% 45,75%
run median 94 bars 41 bars
run max 996 bars 152 bars (dense event chain)
max per-onset lifetime ~996 41 <= SEQ_WINDOW+1 (FIX EVIDENCE)
events removed (bars) — 106.788
```
Interpretation: a single onset now yields TRUE for at most 41 bars (not hundreds).
Run 152 = ~4 consecutive events in a dense cluster (not a single onset).
## H. GOLDEN DATASET IMPACT
Sampling UNCHANGED (same 60 cases). Annotation rebuild:
```text
machine_annotations_f7_v1_LEGACY.csv (before fix — preserved)
machine_annotations_f7_v2.csv (after fix — primary)
f7_v1_vs_v2_comparison.json
summary:
n_cases = 60
cases_changed = 22
cases_unchanged = 38
events_removed = 22
events_added = 0
persistent_state_corrected = 22
f10_f11_unchanged = true
Detail per stratum:
changed : STALE_GRAB 15, EQH_SWEPT 4, EQ_MARGINAL 2, EQL_SWEPT 1
unchanged: FRESH_GRAB 15, AGED_GRAB 10, EQ_NEARCROSS 6, EQL_SWEPT 5, EQH_SWEPT 2
decision v2: YES 45, NO 15 (all NO = STALE_GRAB — stale state is now NO_SWEEP)
```
Note: some EQH/EQL/MARGINAL cases changed on the f7 FIELD (grab state expired),
but machine_decision stays YES via f10/f11 — no semantic information lost.
## I. EXPLICITLY UNCHANGED SEMANTICS
```text
f10/f11 (DetectEQ) : NOT changed — wick condition, close-back (N/A), ATR tolerance
0.10*ATR(row), EQ pair window [r-649, r-50] — SEMANTIC REVIEW REQUIRED
OB / FVG / CHoCH / MSS : NOT changed
timeframe : f7 remains M15; no hidden H4/M30/M3 usage
ML : SniperGold_ML.mqh, _p26_corrected.mqh, train_model.py,
build_features_p2.py, P2.6 baseline — NOT changed
AF_DetectSweep (E2) : OUT OF SCOPE (different implementation, not an ML primitive)
internal g_swpDir : stays legacy (f9/f18 not changed this session)
```
## EVIDENCE STATUS
```text
BUG = CONFIRMED + FIXED (f7 event lifecycle)
SEMANTIC DEFINITION = STILL UNDER REVIEW (f10/f11 rejection, EQ semantics, timeframe)
HUMAN ANNOTATION = NOT STARTED (must target the corrected machine spec,
machine results NOT shown to annotators)
```
## ARTIFACTS
```text
docs/P3_S_F7_EVENT_LIFECYCLE_FORENSIC.md
ml/p3/smc_semantic/smc_semantic_common.py (SEQ_WINDOW + f7_lifecycle)
ml/p3/smc_semantic/machine_annotator.py (v2)
ml/p3/smc_semantic/test_f7_lifecycle.py (R1-R6 + historical)
ml/p3/smc_semantic/output/machine_annotations_f7_v2.csv
ml/p3/smc_semantic/output/f7_v1_vs_v2_comparison.json
ml/p3/smc_semantic/output/machine_annotations_f7_v1_LEGACY.csv (preserved)
ml/p3/smc_semantic/output/cases_meta_v1_LEGACY.json (preserved)
Experts/AlgoForge_Backtest_Baseline.mq5 (patched, 0 errors)
Indicators/Downloads/SniperGold_SMC_ProPlus_v4_4.mq5 (patched, 0 errors)
Indicators/Downloads/SniperGold_SMC_ProPlus_v4_5.mq5 (patched, 0 errors)
```
## HASHES BEFORE FIX (preserved)
```text
AlgoForge_Backtest_Baseline.mq5 (root) : c3fa65846b31f92abdf286ba1b6286466eda03191f83176e808c8f65b8a6839c
SniperGold_ML.mqh : c0d5cae6663f457d2c87750bc8690b47ef4557d0426bfb4183280dc1d1a2f1e5
SniperGold_ML_p26_corrected.mqh : 06df8452a112290ecb9bae1a3dbff6df492e084f8b872885d808bb0303ec6a70
SniperGold_SMC_ProPlus_v4_4.mq5 : 118ffee68760bbd53048fdfc3382a1697fa6870fb3e6d2fd1a4e22eb8e84c2d0
SniperGold_SMC_ProPlus_v4_5.mq5 : 62d25e4f9c63ca189ec366f5c4ddd061839cfdb360a6a5468db8e6db239700b4
smc_semantic_common.py : b754abd60593d84a61147d663f673661ae2089f2c0694586ccf7c1cb25f1acf6
machine_annotator.py : 7b67b5dcd5ac4c0b57f8bf6fbc36ba7a60631031239ef3059590aed528a60602
```