# P3-S.4 FVG FORMAL SPECIFICATION & CODE-CONFORMANCE REPORT ```text Date : 2026-08-22 Session : P3-S.4 — Formal SMC Specification + Code-Conformance Audit (FVG) Scope : Fair Value Gap (FVG / imbalance) — Engine 2 agents C/E (AF_FindFVG), Engine 3 display (AF_CollectFVG), legacy v4.3/v4.4/v4.5 (DetectAndDrawFVG + v4.5 MTF FVG), legacy entry gate (InpEntryOnFVGorOB / FindEntryFVG / Sweep->CHoCH->OB/FVG chain). Principle : SPECIFICATION FIRST, CODE AUDIT SECOND Status : NO CODE CHANGES (Phase D) — all findings DOCUMENTED Artifacts : docs/SMC_FVG_SPEC_v1.md (specification) ml/p3/smc_semantic/spec_tests_fvg.py (+ .json) (tests) ml/p3/smc_semantic/output/spec_tests_fvg_report.json ``` --- ## 0. CHECKPOINT & PROVENANCE (session-start verification) ```text Forge HEAD : 85e3b48993c25323c2ff40040402da548826b1b2 (3 documentation-only commits ahead of the P3-S.3 research checkpoint b6100f9 — Markdown standardization eb8a818, inventory tooling 0ac6ed1, title audit 85e3b48; git diff b6100f9..HEAD touches ONLY .md docs + the md_language_inventory tooling — no research/code change) P3-S.3 commit : b6100f9c4ff631539bab4ba8c5416cae4d89564a VERIFIED P3-S.2 checkpoint : c7a2b3f5e6acbf8deb748315dcbcc200046d0b84 VERIFIED P3-S.0 / P3-S.1 : b519a34396df1304467e45dd223132bed9a6d655 / 8c1ef6c2979b421d15d24d4537bb287fc90396c4 VERIFIED P2 source : 8d330343af688e2de2b2a1d12ce19a582714709a VERIFIED P2.6 model (SHA-256): 06df8452a112290ecb9bae1a3dbff6df492e084f8b872885d808bb0303ec6a70 (Include\SniperGold_ML_p26_corrected.mqh) VERIFIED (file hash match) Branch / remote : main == origin/main (85e3b48) VERIFIED Working tree : CLEAN at start VERIFIED HUMAN VERIFICATION : CANCELLED VERIFIED ``` --- ## A. SOURCE MATERIAL (Phase A — inventory & reconciliation) | # | Source | Location | Role | |---|--------|----------|------| | 1 | DESIGN.md (Algo Forge) | docs/DESIGN.md §C/E + display | Intent: C agent "which zone is price in?" (OB/FVG/S-R/PD); E agent "entry confirmation" (Sweep, CHoCH, displacement, OB/FVG zones; ZONE + CONFIRMATION = setup); display FVG = AFDispZone, MIT filter + size >= 0.02xATR | | 2 | DESAIN_MTF_v45.md | Shared Projects\SniperGold_ML | v4.5 redesign: real per-TF structure (HH/HL/OB/FVG/EQ) via cache; per-TF MTF FVG mitigation on rebuild; view MTF OB/FVG on chart; v4.4 computed FVG only on chart TF | | 3 | v4.3/v4.4 indicator | Indicators\Downloads\SniperGold_SMC_ProPlus_v4_3/4_4.mq5 | DetectAndDrawFVG (v4.3 == v4.4 verified line-identical for FVG): 3-candle gap; minGap = 0.25 x ATR (auto) or 0; HTF projection InpFVGTF; mitigation low<=bot / high>=top; entry gate InpEntryOnFVGorOB + FindEntryFVG tap +- 1 ATR; FVGRec zone struct | | 4 | v4.5 indicator | Indicators\Downloads\SniperGold_SMC_ProPlus_v4_5.mq5 | Same chart DetectAndDrawFVG + per-TF MTF FVG (D1/H4/H1) via cache (0.25 x avg range minGap, per-TF mitigation) | | 5 | Engine 2 FVG detector | Include\AlgoForge\AF_Engine2_Agents.mqh:329-350 (AF_FindFVG) | Geometric 3-candle (reversed index): l0>h2 / h0 top (bear); collects newest maxN unmitigated zones (default 6, max 24) | | 9 | Engine 3 render | Include\AlgoForge\AF_Engine3_Render.mqh:379-392 | draws FVG boxes (top/bot), bull/bear labels | | 10 | Engine 3 indicator | Indicators\AlgoForge\AF_Engine3_Display.mq5 | inputs: InpShowFVG, InpFVGCount=6, colors | | 11 | Unit test | Experts\AlgoForge_Engine3_UnitTest.mq5:133-137,164 | basic zone validity (top>bot, bot>0, tag="FVG") | | 12 | AF_Defines.mqh | Include\AlgoForge\AF_Defines.mqh:31,53,58,61 | AF_E2_FVG_LOOKBACK=40; AF_E3_MAX_ZONES=24; AF_E3_FVG_DEFAULT=6; AF_E3_FVG_MIN_ATR=0.02 | | 13 | FEATURE_CONTRACT | docs/FEATURE_CONTRACT.md | NO FVG feature (0 references) — FVG not in f0-f18 | | 14 | EA runtime | Experts\AlgoForge_Backtest_Baseline.mq5 | NO FVG (0 references) — ML runtime features exclude FVG | | 15 | Python training | ml/**/*.py | NO FVG (0 references) — no training-side FVG | | 16 | P3 docs | P3_S2 conformance (AF_FindFVG context), golden-dataset concept list | FVG listed as a context feature and as the last element of the SMC chain Sweep->CHoCH->OB/FVG | **Layer separation:** ```text Intended semantics : FVG = imbalance ZONE; C agent = "which zone is price in"; E agent = entry zone (ZONE + CONFIRMATION = setup); legacy chain Sweep -> CHoCH -> OB/FVG within InpSeqWindow; display zones with MIT filter + minimum size. Legacy semantics : v4.3/v4.4/v4.5: 3-candle wick gap; minGap 0.25xATR (auto) or 0; mitigation = full fill by wick; entry tap +-1 ATR on ANY unmitigated zone of the side; HTF projection (InpFVGTF); v4.5 per-TF MTF FVG (display). Current semantics : Engine 2 AF_FindFVG = newest FVG ONLY, NO minGap, NO mitigation, lookback 40 (C) / 20 (E); display AF_CollectFVG = newest N unmitigated zones, minGap 0.02xATR, mitigation by close; ML features / EA / training: FVG ABSENT. Training semantics : N/A — FVG is not a training feature (no parity target). Display-only : zone boxes + labels (Engine 3, v4.4/v4.5). ``` --- ## B. PROJECT SEMANTIC SPECIFICATION (Phase B) Full document: **docs/SMC_FVG_SPEC_v1.md** (PROJECT SEMANTIC SPECIFICATION — not "universal SMC ground truth"). Spec decision summary: ```text S-1 Definition : 3-candle: bullish Low(C3) > High(C1), zone [High(C1), Low(C3)]; bearish High(C3) < Low(C1), zone [High(C3), Low(C1)]; C2 extremes unused in the zone bounds. S-2 Gap boundaries : WICK-BASED (High/Low of C1 & C3); no body rule. S-3 Minimum gap : none in the definition (>= 1 tick); zero gap = NOT FVG; consumer filters 0.02/0.25/none = AMBIGUOUS (A-1). S-4 Direction : +1 bullish (up gap), -1 bearish (down gap), 0 none; no trend precondition. S-5 Displacement : NOT REQUIRED (geometric gap sufficient). S-6 Formation : observable at C3 close (b <= t); newest closed bar eligible; canonical timestamp = C3 open. S-7 Closed-bar : all inputs <= t; no future visibility. S-8 Lifecycle : ZONE (persistent); one zone per formation; no event stream. S-9 Mitigation : full fill by wick (Low<=bot bull / High>=top bear); partial fill NOT mitigation; display = close variant (A-2). S-10 Invalidation : NOT MODELED. S-11 Overlap : separate zones per formation; no merge/replace/dedup. S-12 Timeframe : Engine 2 per-TF independent; canonical = AMBIGUOUS (A-3). S-13 Parity : FVG NOT an ML feature (contract f0-f18 has none); parity N/A. ``` --- ## C. FORMAL DEFINITIONS (Phase B — extract) ```text FVG_zone(bar b, prices) with b >= 2 (closed bars), C1=b-2, C2=b-1, C3=b: Bullish FVG (dir=+1): Low(b) > High(b-2) -> zone (bot=High(b-2), top=Low(b)) Bearish FVG (dir=-1): High(b) < Low(b-2) -> zone (bot=High(b), top=Low(b-2)) One zone per qualifying bar b (formations are NOT merged). Zone state (S-9): MITIGATED iff exists j in (b, t] with bull: Low(j) <= bot bear: High(j) >= top (wick full-fill) Canonical consumer query (S-9): the NEWEST UNMITIGATED zone at decision t. No invalidation, no age expiry (S-8/S-10). FVG is not a Feature Contract feature (S-13). ``` --- ## D. CURRENT CODE BEHAVIOR (Phase C — code audit) ### D.1 Engine 2 — AF_FindFVG (AF_Engine2_Agents.mqh:329-350) ```mql5 int AF_FindFVG(const AFEngine1MTF &e1,int slot,int lookback,double &zoneHi,double &zoneLo) { zoneHi=0.0; zoneLo=0.0; if(!e1.IsReady(slot)) return 0; int cnt=e1.Count(slot); if(cnt<3) return 0; int maxIdx=MathMin(cnt-3,(lookback>0)? lookback : cnt); for(int i=1;i<=maxIdx;i++) // i=0 (newest closed bar) SKIPPED { double l0=e1.Low(slot,i); double h2=e1.High(slot,i+2); if(l0>h2) { zoneLo=h2; zoneHi=l0; return 1; } // bullish, NO mit check double h0=e1.High(slot,i); double l2=e1.Low(slot,i+2); if(h0hi2) { bull=true; top=lo0; bot=hi2; found=true; } else if(hi0=0; b--) { if(bull && e1.Close(slot,b)top) { mit=true; break; } // CLOSE above top } if(mit) continue; ... zones[nz] = {t=Time(i), top, bot, bull, tag="FVG"}; } ``` Observations: geometry = S-1; minGap 0.02xATR (A-1); mitigation = CLOSE beyond far boundary (A-2 display variant); collects newest N unmitigated zones; timestamp = C3. ### D.3 Legacy v4.3/v4.4 — DetectAndDrawFVG (v4_4.mq5:592-660; v4_3 identical) ```mql5 double minGap=InpFVGAutoThreshold?0.25*g_atr:0.0; for(int i=startBar+2;ihigh[i-2] && (low[i]-high[i-2])>=minGap) AddFVG(i-1,time[i-1],low[i],high[i-2],true); if(high[i]=minGap) AddFVG(i-1,time[i-1],low[i-2],high[i],false); } // mitigation (wick full-fill) for(...) for(int j=b;j=g_fvg[k].top){ g_fvg[k].mit=true; break; } } // draw newest InpFVGCount unmitigated ``` Observations: geometry = S-1; minGap 0.25xATR (auto) or 0 (A-1); mitigation = wick full-fill (S-9 canonical); C3 = newest closed bar eligible (i can reach total-1); timestamp = C2 (middle candle, A-5); HTF projection via InpFVGTF (A-3). Entry gate: `InpEntryOnFVGorOB` + `FindEntryFVG` = ANY unmitigated zone of the side within +- 1 ATR of price (A-6), closest to zone mid; +10 confluence; signal note "Sweep->CHoCH->Bullish/Bearish FVG (discount/premium)". ### D.4 v4.5 MTF FVG (per-TF structure) Per-TF cache FVG for D1/H4/H1: same geometry + minGap 0.25 x avg range + wick full-fill mitigation, evaluated internally per TF on rebuild (display only). --- ## E. CONFORMANCE MATRIX (Phase C) Verdicts: CONFORMING / PARTIALLY CONFORMING / NON-CONFORMING / UNVERIFIABLE / SPECIFICATION AMBIGUOUS. | # | Requirement | Specification | Code (Function/Line) | Actual Behavior | Verdict | |---|-------------|--------------|----------------------|-----------------|---------| | E-1 | FVG definition | 3-candle gap, zone [High(C1), Low(C3)] / [High(C3), Low(C1)] (S-1) | AF_FindFVG:341,349; AF_CollectFVG:269-272; v4.4:604-605 | all implementations agree on geometry; C2 unused | **CONFORMING** | | E-2 | Gap boundaries | WICK-BASED (High/Low of C1 & C3) (S-2) | all: Low vs High comparisons | wick extremes; no body/close rule | **CONFORMING** | | E-3 | Minimum gap | definition: >= 1 tick; zero gap NOT FVG; filters are consumer config (S-3) | AF_FindFVG none; AF_CollectFVG 0.02xATR (:273); v4.4 0.25xATR auto (:598) | three different filters; no canonical threshold | **SPECIFICATION AMBIGUOUS** (A-1) | | E-4 | Direction | +1 bullish / -1 bearish / 0 none; no trend precondition (S-4) | AF_FindFVG:346,353; bull flags everywhere | gap direction; no prior-trend gate | **CONFORMING** | | E-5 | Displacement | NOT REQUIRED (S-5) | no displacement check in any FVG path | geometric gap sufficient | **CONFORMING** | | E-6 | Formation timing | observable at C3 close; newest closed bar eligible as C3 (S-6) | v4.4:602 itop (:279-283); v4.4 low<=bot / high>=top (:634-635) | Engine 2 consumes mitigated zones; display uses close variant; legacy uses wick | **NON-CONFORMING** (Engine 2, BUG-P3S4-001) + **SPECIFICATION AMBIGUOUS** (A-2 close vs wick) | | E-10 | Invalidation | NOT MODELED (S-10) | no invalidation code anywhere | none exists | **CONFORMING** | | E-11 | Overlap / multiple | separate zones per formation; no merge (S-11) | independent AddFVG per bar; zones arrays | consecutive formations -> separate zones; no dedup | **CONFORMING** | | E-12 | Timeframe | Engine 2 per-TF; canonical AMBIGUOUS (S-12) | AF_FindFVG per slot (H4/M30/M15/M3); v4.5 MTF cache; InpFVGTF | per-TF independent; HTF role not defined | **SPECIFICATION AMBIGUOUS** (A-3) | | E-13 | Runtime/training parity | FVG NOT an ML feature; parity N/A (S-13) | FEATURE_CONTRACT/EA/ml: 0 FVG references | no training-side FVG; no parity target | **CONFORMING** (N/A by absence) | | E-14 | Consumer zone scope | canonical consumer = newest UNMITIGATED zone (S-9) | AF_FindFVG newest-ANY (no mit); FindEntryFVG all-unmitigated; AF_CollectFVG newest-N-unmitigated | Engine 2 zone selection diverges from legacy entry semantics | **PARTIALLY CONFORMING** (BUG-P3S4-001 / A-6) | | E-15 | Consumer lookback | single canonical window (S-6 note) | C agent 40 vs E agent 20 (AF_E2_FVG_LOOKBACK vs hardcoded) | C sees an FVG the E agent cannot | **PARTIALLY CONFORMING** (BUG-P3S4-002) | --- ## F. CONFIRMED BUGS (Phase D — DOCUMENT ONLY, no code changes) ```text BUG-P3S4-001 SEVERITY : MEDIUM SOURCE : AF_FindFVG — AF_Engine2_Agents.mqh:329-350 (Engine 2 C/E agents) SPEC REQ : S-9 — mitigation is part of the FVG zone lifecycle; the canonical consumer query is the newest UNMITIGATED zone ACTUAL CODE : AF_FindFVG returns the newest FVG with NO mitigation check; it also returns ONLY the newest zone (older unmitigated zones invisible to the agents) IMPACT : C agent "price in FVG zone" (weight 0.25) and E agent "zone tap" can fire on a FULLY-FILLED (mitigated) FVG; the zone selection (newest-any) differs from the legacy entry rule (all-unmitigated within tap). The f7/f9/f18 duplication pattern does NOT apply (FVG is a zone, not an event stream), but the mitigation lifecycle is not respected by the current detector. PROPOSED FIX : add the wick full-fill mitigation filter (S-9) to AF_FindFVG and (if intended) scan for the newest unmitigated zone instead of the newest-any; document the zone-selection rule. BUG-P3S4-002 SEVERITY : LOW SOURCE : AF_FindFVG loop bound — AF_Engine2_Agents.mqh:338 (`i=1`) and callers (C:40 / E:20) SPEC REQ : S-6 — the newest closed bar is eligible as C3; a single canonical lookback window ACTUAL CODE : loop starts at i=1 (index 0 skipped) -> FVG whose C3 is the newest closed bar is missed until one bar later (1-bar lag); C agent lookback 40 vs E agent hardcoded 20 IMPACT : Engine-2 FVG lags the legacy/display detection by 1 bar; the C and E agents may disagree on FVG presence/age (E window 20 vs C 40) PROPOSED FIX : start the scan at i=0 (subject to the closed-bar lock) or document the 1-bar maturity delay; unify the lookback constant. BUG-P3S4-003 SEVERITY : INFO (display only) SOURCE : zone timestamp/bar conventions SPEC REQ : S-6/A-5 — canonical timestamp = C3 open ACTUAL CODE : v4.4/v4.5 AddFVG(i-1, time[i-1]) = middle candle C2; Engine-3 display = C3; Engine 2 = none IMPACT : box start times differ between legacy and Engine-3 displays; no ML/feature impact PROPOSED FIX : unify the zone timestamp at C3 (display only). BUG-P3S4-004 SEVERITY : INFO (specification ambiguity) SOURCE : minimum-gap filters — AF_Defines.mqh:61 (0.02 ATR) vs v4.4:598 (0.25 ATR auto) vs AF_FindFVG (none) SPEC REQ : S-3/A-1 — a canonical project minimum-gap threshold ACTUAL CODE : three different consumer filters; no canonical value IMPACT : the same price sequence may be "FVG" in Engine 2, "not FVG" in display, and "not FVG" in v4.4 (auto) depending on gap size PROPOSED FIX : adjudicate a single project threshold (NOT optimized here) or explicitly scope the filters to their consumers ``` --- ## G. SEMANTIC AMBIGUITIES (Phase F — consistency) ```text G-1 MINIMUM GAP FILTERS (A-1) Engine 2 none / display 0.02 x ATR / legacy auto 0.25 x ATR. No canonical project threshold; no optimization performed in this session. G-2 MITIGATION TRIGGER (A-2) Legacy = full fill by WICK (low<=bot / high>=top); display = full fill by CLOSE; Engine 2 = none (BUG-P3S4-001). Partial fill not modeled anywhere. G-3 CANONICAL TIMEFRAME (A-3) Engine-2 M15 slot explicit; HTF FVG as M15 context and M3 FVG as entry trigger not defined. Same class as CHoCH G-4 / sweep G-3. G-4 SAME-BAR DOUBLE CONDITION (A-4) Bull and bear cannot both be true for one C3 (geometrically); bull-first evaluation; unreachable. G-5 ZONE TIMESTAMP (A-5) v4.4/v4.5 = C2 middle; Engine-3 display = C3; Engine 2 = none. Display-only. G-6 CONSUMER ZONE SCOPE (A-6) Engine 2 = newest zone only; legacy entry = all unmitigated within tap; display = newest N unmitigated. Different selection semantics. ``` --- ## H. SEMANTIC RELATIONSHIP WITH THE SMC CHAIN (Phase C) ```text Detection : FVG detection STANDS ALONE (pure geometric gap; no sweep/CHoCH required) — CONFORMING S-1/S-4/S-5. Legacy chain : Sweep -> CHoCH -> OB/FVG within InpSeqWindow (v4.4) — FVG is the final ENTRY ZONE of the chain; ordering/freshness handled by the sweep/CHoCH gates (P3-S.2/P3-S.3 audits), the FVG zone itself has no age rule (mitigation is its only termination). Engine 2 : C agent = FVG as CONTEXT (price-in-zone); E agent = FVG as ENTRY ZONE with ZONE + CONFIRMATION = setup (DESIGN.md). Consistent with intent. ML : FVG ABSENT from f0-f18 — the chain is runtime/display only. NO production dependency between FVG and f7/f8/f9/f10/f11 was changed. ``` --- ## I. RUNTIME/TRAINING PARITY (Phase C — diagnostic, not a retrain) ```text FVG is not a Feature Contract feature (f0-f18) and has no Python training representation (verified: 0 FVG references in FEATURE_CONTRACT.md, EA, ml/**/*.py). -> runtime/training parity for FVG = N/A BY ABSENCE (S-13). No mismatch exists; the absence itself is a documented fact, not a defect. If FVG is later promoted to an ML feature, a Feature Contract entry and a parity harness are required first (out of scope). ``` --- ## J. VERDICT ```text PARTIALLY CONFORMING Detection semantics (E-1, E-2, E-4, E-5, E-7) : CONFORMING Minimum gap (E-3) : SPECIFICATION AMBIGUOUS (A-1) Formation timing (E-6) : PARTIALLY CONFORMING (BUG-P3S4-002) Lifecycle zone (E-8) : CONFORMING (no event duplication) Mitigation (E-9) : NON-CONFORMING (Engine 2, BUG-P3S4-001) + AMBIGUOUS (A-2 close vs wick) Invalidation (E-10) : CONFORMING (not modeled) Overlap / multiple (E-11) : CONFORMING Timeframe (E-12) : SPECIFICATION AMBIGUOUS (A-3) Consumer semantics (E-14, E-15) : PARTIALLY CONFORMING (BUG-P3S4-001/-002, A-6) Runtime/training parity (E-13) : CONFORMING (N/A by absence) Verdict = conformance to the PROJECT SEMANTIC SPECIFICATION, NOT profitability/edge. The DETECTOR core (geometry/direction/closed-bar/zone lifecycle) is conforming; the gaps are in consumer-side semantics (mitigation, newest-zone scope, 1-bar lag, lookback split, canonical threshold/timeframe). ``` --- ## K. NEXT GATE ```text After the FVG verdict (PARTIALLY CONFORMING): OB -> Displacement -> MTF Alignment -> Candidate Setup. DO NOT return to ML; DO NOT build a meta-label; DO NOT create new event labels; DO NOT fix production code before the audit chain completes (all fixes stay documented as BUG-P3S4-00x until the semantic audit chain is finished). ``` --- ## L. CHECKPOINT & PROVENANCE (P3-S.4) ```text Forge HEAD (session start) : 85e3b48 (P3-S.3 research checkpoint b6100f9 intact; ahead only by 3 documentation-only commits) P3-S.3 spec (immutable) : docs/SMC_CHOCH_MSS_SPEC_v1.md P3-S.2 spec (immutable) : docs/SMC_LIQUIDITY_SWEEP_SPEC_v1.md FEATURE_CONTRACT : C44CC6F2... (P2-era) / 7b908b12... (committed) symbol/tf : XAUUSD / M15 (2017-01-01 .. 2026-08-20) Human verification : CANCELLED No production change : AF_FindFVG / AF_CollectFVG / v4.3/v4.4/v4.5 / Engine 2 / Engine 3 / f7-f18 / OB / CHoCH / Displacement / ML : NOT touched ```