SniperGold_ML/ml/p3/smc_semantic/spec_test_cases_fvg.json

378 lines
16 KiB
JSON
Raw Permalink Normal View History

{
"meta": {
"spec_doc": "docs/SMC_FVG_SPEC_v1.md",
"spec_version": "v1",
"phase": "P3-S.4",
"principle": "Expected results derived from PROJECT SEMANTIC SPECIFICATION (S-1..S-13), NOT from current implementation. Code port results are reported for conformance observation, not as truth.",
"constants": {
"FVG_LOOKBACK": 40,
"ENGINE2_LOOKBACK_C": 40,
"ENGINE2_LOOKBACK_E": 20,
"DISPLAY_MIN_ATR": 0.02,
"LEGACY_AUTO_MIN_ATR": 0.25,
"SYMBOL": "XAUUSD",
"DECISION_TF": "M15"
},
"bar_format": "[open, high, low, close] per bar, chronological (index 0 = oldest). All bars are CLOSED up to decision_bar (the newest closed bar); bars beyond decision_bar are future/forming and MUST NOT influence the decision.",
"zone_format": "[formation_bar(C3), dir, top, bot, mit] — dir +1 bullish / -1 bearish; top/bot zone bounds (S-1); mit 1 = mitigated (wick full-fill, S-9).",
"newest_unmitigated_format": "[bar, dir, top, bot] of the newest UNMITIGATED zone at the decision bar (canonical consumer query S-9), or null if none.",
"code_newest_expected": "Engine-2 AF_FindFVG observed result [dir, top, bot] (or null): newest FVG with NO mitigation filter and 1-bar lag (C3 min = decision_bar-1). Reported as conformance observation; divergence documents BUG-P3S4-001/-002.",
"note": "All 20 required cases (FVG-T01..T20). Expected outputs are the SPEC truth; code outputs are observations."
},
"cases": [
{
"id": "FVG-T01",
"title": "Valid bullish FVG",
"rule": "SPEC S-1/S-4 — Low(C3) > High(C1), zone [High(C1), Low(C3)], dir=+1",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]], [5, [100.6, 100.8, 100.45, 100.7]]]
},
"decision_bar": 5,
"expected": {
"zones": [[4, 1, 100.4, 100.2, 0]],
"zone_count": 1,
"newest_unmitigated": [4, 1, 100.4, 100.2],
"code_newest_expected": [1, 100.4, 100.2]
}
},
{
"id": "FVG-T02",
"title": "Valid bearish FVG",
"rule": "SPEC S-1/S-4 — High(C3) < Low(C1), zone [High(C3), Low(C1)], dir=-1",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": [[2, [100.3, 100.5, 100.0, 100.4]], [3, [100.0, 100.2, 99.6, 99.8]], [4, [99.6, 99.8, 99.2, 99.5]], [5, [99.4, 99.6, 99.1, 99.5]]]
},
"decision_bar": 5,
"expected": {
"zones": [[4, -1, 100.0, 99.8, 0]],
"zone_count": 1,
"newest_unmitigated": [4, -1, 100.0, 99.8],
"code_newest_expected": [-1, 100.0, 99.8]
}
},
{
"id": "FVG-T03",
"title": "No gap",
"rule": "SPEC S-1 — no Low(C3) > High(C1) / High(C3) < Low(C1) anywhere -> NO zones",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": []
},
"decision_bar": 5,
"expected": {
"zones": [],
"zone_count": 0,
"newest_unmitigated": null,
"code_newest_expected": null
}
},
{
"id": "FVG-T04",
"title": "Gap exactly at minimum threshold (1 tick)",
"rule": "SPEC S-3 — strictly positive gap is valid; gap = 1 tick (0.1) -> FVG",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.3, 100.9]], [5, [100.6, 100.8, 100.45, 100.7]]]
},
"decision_bar": 5,
"expected": {
"zones": [[4, 1, 100.3, 100.2, 0]],
"zone_count": 1,
"newest_unmitigated": [4, 1, 100.3, 100.2],
"code_newest_expected": [1, 100.3, 100.2]
}
},
{
"id": "FVG-T05",
"title": "Gap one tick below threshold (zero gap)",
"rule": "SPEC S-3 — Low(C3) == High(C1) is NOT an FVG (strict >) -> NO zone",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.3, 100.8, 100.2, 100.7]], [5, [100.6, 100.8, 100.45, 100.7]]]
},
"decision_bar": 5,
"expected": {
"zones": [],
"zone_count": 0,
"newest_unmitigated": null,
"code_newest_expected": null
}
},
{
"id": "FVG-T06",
"title": "Gap one tick above threshold (2 ticks)",
"rule": "SPEC S-3 — gap = 2 ticks (0.2) -> valid FVG (spec has no larger minimum)",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]], [5, [100.6, 100.8, 100.45, 100.7]]]
},
"decision_bar": 5,
"expected": {
"zones": [[4, 1, 100.4, 100.2, 0]],
"zone_count": 1,
"newest_unmitigated": [4, 1, 100.4, 100.2],
"code_newest_expected": [1, 100.4, 100.2]
}
},
{
"id": "FVG-T07",
"title": "Current candle still forming cannot create an FVG",
"rule": "SPEC S-6/S-7 — the forming bar (beyond decision_bar) is not closed; a candidate C3 beyond t is NOT observable",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 7,
"patches": [[4, [100.0, 100.2, 99.9, 100.1]], [5, [100.3, 100.9, 100.25, 100.8]], [6, [100.5, 101.0, 100.4, 100.9]]]
},
"decision_bar": 5,
"expected": {
"zones": [],
"zone_count": 0,
"newest_unmitigated": null,
"code_newest_expected": null,
"note": "bar 6 (forming, Low 100.4 > High 4 = 100.2) would form an FVG but is beyond decision_bar 5 -> not observable (S-6)."
}
},
{
"id": "FVG-T08",
"title": "FVG becomes valid only after the third candle closes",
"rule": "SPEC S-6 — C3 must be closed (b <= t); at t=3 the C3=4 formation is not yet valid",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 5,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]]]
},
"decision_bar": 3,
"expected": {
"zones": [],
"zone_count": 0,
"newest_unmitigated": null,
"code_newest_expected": null,
"note": "pair with FVG-T01: at t=3 (C3=4 not closed) NO FVG; at t>=4 the FVG exists."
}
},
{
"id": "FVG-T09",
"title": "Partial mitigation is NOT mitigation",
"rule": "SPEC S-9 — price entering the zone (Low inside [bot,top]) but not reaching bot -> UNMITIGATED",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 7,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]], [5, [100.6, 100.8, 100.45, 100.7]], [6, [100.1, 100.45, 100.3, 100.2]]]
},
"decision_bar": 6,
"expected": {
"zones": [[4, 1, 100.4, 100.2, 0]],
"zone_count": 1,
"newest_unmitigated": [4, 1, 100.4, 100.2],
"code_newest_expected": [1, 100.4, 100.2],
"note": "bar 6 Low 100.3 is INSIDE the zone [100.2, 100.4] (partial fill) -> NOT mitigated (S-9)."
}
},
{
"id": "FVG-T10",
"title": "Full mitigation (wick reaches zone bottom)",
"rule": "SPEC S-9 — subsequent Low <= bot -> MITIGATED; canonical consumer query returns null",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 7,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]], [5, [100.6, 100.8, 100.45, 100.7]], [6, [100.1, 100.45, 100.1, 100.2]]]
},
"decision_bar": 6,
"expected": {
"zones": [[4, 1, 100.4, 100.2, 1]],
"zone_count": 1,
"newest_unmitigated": null,
"code_newest_expected": [1, 100.4, 100.2],
"note": "bar 6 Low 100.1 <= bot 100.2 -> full fill by wick -> mitigated. Engine-2 code STILL returns it (BUG-P3S4-001): code [1,...] vs spec null."
}
},
{
"id": "FVG-T11",
"title": "Invalidation is NOT modeled (close-through + opposite displacement)",
"rule": "SPEC S-10 — a close-through / opposite move only MITIGATES the zone; there is no separate INVALIDATED state",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 8,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]], [5, [100.6, 100.8, 100.45, 100.7]], [6, [100.55, 100.7, 100.5, 100.6]], [7, [100.2, 100.55, 99.9, 100.0]]]
},
"decision_bar": 7,
"expected": {
"zones": [[4, 1, 100.4, 100.2, 1]],
"zone_count": 1,
"newest_unmitigated": null,
"code_newest_expected": [1, 100.4, 100.2],
"note": "bar 7 closes through the zone (close 100.0 < bot) with an opposite move -> zone is MITIGATED only; no invalidation state exists (S-10)."
}
},
{
"id": "FVG-T12",
"title": "Overlapping FVGs (4-bar move, 3 candidate C3 bars)",
"rule": "SPEC S-11 — every qualifying bar produces its OWN zone; zones are NOT merged",
"bar_spec": {
"neutral": [100.0, 100.3, 99.9, 100.2],
"count": 6,
"patches": [[1, [100.1, 100.5, 100.0, 100.4]], [2, [100.3, 100.6, 100.2, 100.5]], [3, [100.6, 100.9, 100.55, 100.8]], [4, [100.7, 101.0, 100.65, 100.9]], [5, [100.9, 101.2, 100.95, 101.1]]]
},
"decision_bar": 5,
"expected": {
"zones": [[3, 1, 100.55, 100.5, 0], [4, 1, 100.65, 100.6, 0], [5, 1, 100.95, 100.9, 0]],
"zone_count": 3,
"newest_unmitigated": [5, 1, 100.95, 100.9],
"code_newest_expected": [1, 100.65, 100.6],
"note": "3 separate zones (b=3,4,5). Engine-2 code returns the bar-4 zone (C3 = decision_bar-1 = 4, 1-bar lag): code [1,100.65,100.6] vs spec newest [5,1,100.95,100.9] (BUG-P3S4-002)."
}
},
{
"id": "FVG-T13",
"title": "Multiple consecutive FVGs (separated formations)",
"rule": "SPEC S-11 — separate formations produce separate zones; no merge/replace",
"bar_spec": {
"neutral": [100.0, 100.3, 99.9, 100.2],
"count": 7,
"patches": [[1, [100.1, 100.5, 100.0, 100.4]], [2, [100.3, 100.6, 100.2, 100.5]], [3, [100.6, 100.9, 100.55, 100.8]], [4, [100.7, 100.9, 100.6, 100.8]], [5, [100.7, 101.0, 100.65, 100.9]], [6, [101.0, 101.3, 100.95, 101.2]]]
},
"decision_bar": 6,
"expected": {
"zones": [[3, 1, 100.55, 100.5, 0], [6, 1, 100.95, 100.9, 0]],
"zone_count": 2,
"newest_unmitigated": [6, 1, 100.95, 100.9],
"code_newest_expected": [1, 100.55, 100.5],
"note": "zones at b=3 and b=6 coexist. Engine-2 code (lag + scan) returns the OLDER b=3 zone: code [1,100.55,100.5] vs spec newest [6,...] (BUG-P3S4-002)."
}
},
{
"id": "FVG-T14",
"title": "Persistent zone is ONE FVG, not many events",
"rule": "SPEC S-8 — a zone untraded for 20 bars is ONE zone; no repeated events",
"bar_spec": {
"neutral": [100.6, 100.9, 100.5, 100.8],
"count": 25,
"patches": [[0, [100.6, 100.9, 100.2, 100.8]], [1, [100.6, 100.9, 100.2, 100.8]], [2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]]]
},
"decision_bar": 24,
"expected": {
"zones": [[4, 1, 100.4, 100.2, 0]],
"zone_count": 1,
"newest_unmitigated": [4, 1, 100.4, 100.2],
"code_newest_expected": [1, 100.4, 100.2],
"note": "20 bars after formation the zone is STILL ONE zone (zone_count=1), unmitigated (no low <= 100.2), no age expiry (S-8/S-10). The f7/f9/f18 duplication pattern does NOT apply to FVG."
}
},
{
"id": "FVG-T15",
"title": "Future-bar mutation must not change the historical FVG decision",
"rule": "SPEC S-7 — property test: mutating bars beyond decision_bar leaves zones unchanged",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]], [5, [100.6, 100.8, 100.45, 100.7]]]
},
"decision_bar": 5,
"mutations": [[20, [200.0, 210.0, 199.0, 205.0]]],
"expected": {
"zones": [[4, 1, 100.4, 100.2, 0]],
"zone_count": 1,
"newest_unmitigated": [4, 1, 100.4, 100.2],
"code_newest_expected": [1, 100.4, 100.2]
}
},
{
"id": "FVG-T16",
"title": "Bullish/bearish symmetry",
"rule": "SPEC S-4 — mirror of FVG-T01: symmetric bearish zone; runner also verifies mirror property",
"bar_spec": {
"neutral": [100.0, 100.2, 99.5, 99.7],
"count": 6,
"patches": [[2, [100.0, 100.1, 99.8, 99.9]], [3, [99.7, 99.8, 99.2, 99.4]], [4, [99.4, 99.6, 99.0, 99.3]], [5, [99.3, 99.5, 99.0, 99.4]]]
},
"decision_bar": 5,
"expected": {
"zones": [[4, -1, 99.8, 99.6, 0]],
"zone_count": 1,
"newest_unmitigated": [4, -1, 99.8, 99.6],
"code_newest_expected": [-1, 99.8, 99.6]
}
},
{
"id": "FVG-T17",
"title": "Insufficient history (< 3 bars)",
"rule": "SPEC S-1/S-6 — fewer than 3 closed bars -> NO FVG possible",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 2,
"patches": []
},
"decision_bar": 1,
"expected": {
"zones": [],
"zone_count": 0,
"newest_unmitigated": null,
"code_newest_expected": null
}
},
{
"id": "FVG-T18",
"title": "Timeframe boundary (TF-agnostic geometry)",
"rule": "SPEC S-12 — the FVG geometry is TF-agnostic; the same closed sequence yields the same zone on any TF; canonical project FVG TF = AMBIGUOUS (A-3)",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.3, 100.9, 100.25, 100.8]], [4, [100.5, 101.0, 100.4, 100.9]], [5, [100.6, 100.8, 100.45, 100.7]]]
},
"decision_bar": 5,
"tf_agnostic": true,
"expected": {
"zones": [[4, 1, 100.4, 100.2, 0]],
"zone_count": 1,
"newest_unmitigated": [4, 1, 100.4, 100.2],
"code_newest_expected": [1, 100.4, 100.2],
"note": "same data on M15 vs H4 -> identical zone (per-TF independence, Engine 2). Which TF is the canonical entry FVG = SPECIFICATION AMBIGUOUS (A-3)."
}
},
{
"id": "FVG-T19",
"title": "Displacement is NOT required (small-body gap candle)",
"rule": "SPEC S-5 — a geometric gap alone is sufficient; the middle candle C2 may have a tiny body",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": [[2, [100.0, 100.2, 99.9, 100.1]], [3, [100.25, 100.3, 100.2, 100.25]], [4, [100.5, 101.0, 100.4, 100.9]], [5, [100.35, 100.6, 100.3, 100.5]]]
},
"decision_bar": 5,
"expected": {
"zones": [[4, 1, 100.4, 100.2, 0]],
"zone_count": 1,
"newest_unmitigated": [4, 1, 100.4, 100.2],
"code_newest_expected": [1, 100.4, 100.2],
"note": "C2 body = 0.05 (weak displacement) -> FVG still valid (DISPLACEMENT = NOT REQUIRED BY CURRENT SPEC)."
}
},
{
"id": "FVG-T20",
"title": "Runtime/training parity: N/A by absence",
"rule": "SPEC S-13 — FVG is NOT a Feature Contract feature; no training-side FVG exists; the runner scans FEATURE_CONTRACT.md + ml/**/*.py for FVG references and expects 0",
"bar_spec": {
"neutral": [100.0, 100.5, 99.8, 100.3],
"count": 6,
"patches": []
},
"decision_bar": 5,
"parity_na": true,
"expected": {
"zones": [],
"zone_count": 0,
"newest_unmitigated": null,
"code_newest_expected": null,
"note": "structural: FVG absent from f0-f18 (FEATURE_CONTRACT), EA runtime, and Python training -> no parity target (documented, not a mismatch)."
}
}
]
}