213 lines
10 KiB
JSON
213 lines
10 KiB
JSON
|
|
{
|
||
|
|
"meta": {
|
||
|
|
"spec_doc": "docs/SMC_DISPLACEMENT_SPEC_v1.md",
|
||
|
|
"spec_version": "v1",
|
||
|
|
"phase": "P3-S.6",
|
||
|
|
"principle": "Expected results derived from PROJECT SEMANTIC SPECIFICATION (S-1..S-14), NOT from current implementation. Code port results are reported for conformance observation, not as truth.",
|
||
|
|
"constants": {
|
||
|
|
"AVG_N": 20,
|
||
|
|
"K": 1.6,
|
||
|
|
"OB_MOVE_BODY_MULT": 1.5,
|
||
|
|
"SYMBOL": "XAUUSD",
|
||
|
|
"DECISION_TF": "M15"
|
||
|
|
},
|
||
|
|
"bar_format": "[open, high, low, close] per bar, chronological (index 0 = oldest). Displacement is evaluated on the NEWEST CLOSED bar (decision_bar) only (S-1/S-9).",
|
||
|
|
"displacement_format": "dir of the newest closed bar: +1 bullish (body >= 1.6 x avg AND Close>Open), -1 bearish, 0 otherwise (S-1/S-4/S-10).",
|
||
|
|
"code_dir_expected": "Engine-2 AF_DetectDisplacement observed result (identical formula — the implementation IS the audited primitive). Reported as conformance observation.",
|
||
|
|
"note": "All 20 required cases (DP-T01..T20). Expected outputs are the SPEC truth; code outputs are observations."
|
||
|
|
},
|
||
|
|
"cases": [
|
||
|
|
{
|
||
|
|
"id": "DP-T01",
|
||
|
|
"title": "Valid bullish displacement",
|
||
|
|
"rule": "SPEC S-1/S-4 — body >= 1.6 x avg AND Close > Open -> +1",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.3]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T02",
|
||
|
|
"title": "Valid bearish displacement",
|
||
|
|
"rule": "SPEC S-4 — body >= 1.6 x avg AND Close < Open -> -1",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.3, 100.5, 99.7, 100.0]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": -1, "code_dir_expected": -1}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T03",
|
||
|
|
"title": "Large range but small body -> NOT displacement",
|
||
|
|
"rule": "SPEC S-2 — (High-Low) plays NO role; body 0.1 < 1.6 x avg -> 0",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 101.0, 99.0, 100.1]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 0, "code_dir_expected": 0}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T04",
|
||
|
|
"title": "Large body but small full range -> displacement",
|
||
|
|
"rule": "SPEC S-2 — body-based rule; range irrelevant; body 0.3 >= 1.6 x avg -> +1",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.31, 99.99, 100.3]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T05",
|
||
|
|
"title": "Exactly at threshold (inclusive)",
|
||
|
|
"rule": "SPEC S-10 — body == 1.6 x avg (within float precision) IS displacement (>=)",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.1652174]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1,
|
||
|
|
"note": "body 0.1652174 = 1.6 x avg (avg=(1.9+body)/20=0.10326087, thr=0.16521739); inclusive boundary confirmed."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T06",
|
||
|
|
"title": "One tick below threshold -> NOT displacement",
|
||
|
|
"rule": "SPEC S-10 — body < 1.6 x avg -> 0 (strict <)",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.1642174]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 0, "code_dir_expected": 0}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T07",
|
||
|
|
"title": "One tick above threshold -> displacement",
|
||
|
|
"rule": "SPEC S-10 — body > 1.6 x avg -> +1",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.1662174]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T08",
|
||
|
|
"title": "Insufficient historical baseline (window shrinks)",
|
||
|
|
"rule": "SPEC S-3 — with < 20 bars the window = min(20, count); the rule still applies",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 6,
|
||
|
|
"patches": [[5, [100.0, 100.6, 99.9, 100.3]]]},
|
||
|
|
"decision_bar": 5,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1,
|
||
|
|
"note": "avg over 6 bars = (5x0.1+0.3)/6 = 0.1333, thr = 0.2133 < body 0.3 -> +1."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T09",
|
||
|
|
"title": "Current candle still forming is NOT evaluated",
|
||
|
|
"rule": "SPEC S-1/S-10 — displacement uses the NEWEST CLOSED bar; the forming bar (beyond t) is excluded",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.3]]]},
|
||
|
|
"decision_bar": 23,
|
||
|
|
"expected": {"dir": 0, "code_dir_expected": 0,
|
||
|
|
"note": "bar 24 (would-be displacement) is forming beyond t=23; bar 23 is neutral -> 0."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T10",
|
||
|
|
"title": "Valid only after candle close",
|
||
|
|
"rule": "SPEC S-10 — at t=24 the bar closed -> displacement observable (+1); pair with DP-T09",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.3]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T11",
|
||
|
|
"title": "Bullish/bearish symmetry",
|
||
|
|
"rule": "SPEC S-11 — mirror of DP-T01; runner asserts mirror property on every case",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.3, 100.5, 99.7, 100.0]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": -1, "code_dir_expected": -1}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T12",
|
||
|
|
"title": "Large candle WITHOUT structural break -> displacement",
|
||
|
|
"rule": "SPEC S-5 — NO structural requirement; a large body in a flat sequence IS displacement",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.3]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1,
|
||
|
|
"note": "no BOS/CHoCH/sweep/FVG/OB in the data -> displacement stands alone."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T13",
|
||
|
|
"title": "Structural break WITHOUT sufficient displacement",
|
||
|
|
"rule": "SPEC S-5 — a close beyond a level with a small body (< 1.6 x avg) is NOT displacement",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.4, 100.6, 100.3, 100.5]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 0, "code_dir_expected": 0,
|
||
|
|
"note": "close 100.5 above the prior range (structural break) but body 0.1 < thr -> 0."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T14",
|
||
|
|
"title": "Displacement followed by FVG (correlated, NOT required)",
|
||
|
|
"rule": "SPEC S-6 — FVG dependency NOT REQUIRED; displacement detected even when an FVG also forms",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 100.4, 100.3]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1,
|
||
|
|
"note": "bar 24 body 0.3 -> +1; Low(24)=100.4 > High(22)=100.3 -> an FVG also forms; FVG NOT required by displacement."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T15",
|
||
|
|
"title": "Large candle but NO FVG -> displacement still detected",
|
||
|
|
"rule": "SPEC S-6 — displacement is independent of FVG; no FVG -> displacement remains",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 100.25, 100.3]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1,
|
||
|
|
"note": "Low(24)=100.25 <= High(22)=100.3 -> no FVG; displacement still +1."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T16",
|
||
|
|
"title": "Displacement and Order Block relationship",
|
||
|
|
"rule": "SPEC S-7 — displacement body 0.6 also satisfies the OB strong-move gate (1.5 x avg); same concept family",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[23, [100.2, 100.5, 99.8, 100.1]], [24, [100.3, 101.0, 100.2, 100.9]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1,
|
||
|
|
"note": "bar 24 body 0.6 >= 1.6 x avg (0.2) -> displacement +1; also >= 1.5 x avg -> OB strong-move gate satisfied on the same candle (BUG-P3S6-001: 1.5 vs 1.6)."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T17",
|
||
|
|
"title": "Displacement and CHoCH relationship",
|
||
|
|
"rule": "SPEC S-8 — CHoCH is close-confirmed structure, displacement is body-only; a small-body CHoCH-like bar is NOT displacement",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.4, 100.6, 100.3, 100.5]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"expected": {"dir": 0, "code_dir_expected": 0,
|
||
|
|
"note": "CHoCH does NOT require displacement (P3-S.3 S-6); displacement = 0 on this bar."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T18",
|
||
|
|
"title": "Repeated bars after one displacement -> no duplicate events",
|
||
|
|
"rule": "SPEC S-9 — displacement is a per-bar candle attribute; the NEXT bar is re-evaluated independently (no carry-forward)",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 26,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.3]]]},
|
||
|
|
"decision_bar": 25,
|
||
|
|
"expected": {"dir": 0, "code_dir_expected": 0,
|
||
|
|
"note": "bar 24 was displacement (+1 at t=24, see DP-T01); at t=25 the newest bar (neutral body 0.1) gives 0 -> no persistence, no repeated events."}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T19",
|
||
|
|
"title": "Future-bar mutation must not change the historical result",
|
||
|
|
"rule": "SPEC S-3 — property test: mutating bars beyond t leaves the displacement at t unchanged",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.3]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"mutations": [[30, [200.0, 210.0, 199.0, 205.0]]],
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "DP-T20",
|
||
|
|
"title": "Timeframe boundary (TF-agnostic geometry)",
|
||
|
|
"rule": "SPEC S-12 — the displacement rule is TF-agnostic; canonical project displacement TF = AMBIGUOUS (A-1)",
|
||
|
|
"bar_spec": {"neutral": [100.0, 100.3, 99.9, 100.1], "count": 25,
|
||
|
|
"patches": [[24, [100.0, 100.6, 99.9, 100.3]]]},
|
||
|
|
"decision_bar": 24,
|
||
|
|
"tf_agnostic": true,
|
||
|
|
"expected": {"dir": 1, "code_dir_expected": 1}
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|