// ═══════════════════════════════════════════════════════════════════════ // SMC & ICT Strategy Compendium — Oyamori (Pine Script v6) // Ported from the Python reference: smc_ict_strategies.py // // Learning reference, NOT a proven trading system. Every function below is // a direct translation of the rule described in Oyamori's SMC & ICT // Fundamentals course (Lessons 1-11) — nothing has been added, and nothing // here has been backtested or optimized. Pick one strategy from the // dropdown, review its entries on the Strategy Tester tab yourself. // ═══════════════════════════════════════════════════════════════════════ //@version=6 strategy("SMC & ICT Strategy Compendium — Oyamori", overlay=true, max_boxes_count=100, max_lines_count=100, max_labels_count=100, default_qty_type=strategy.percent_of_equity, default_qty_value=10) // ── Inputs ───────────────────────────────────────────────────────────── strategySelect = input.string("OTE + Order Block Confluence", "Strategy", options=[ "OTE + Order Block Confluence", "Break-and-Retest", "Turtle Soup", "Silver Bullet", "2022 Model", "Judas Swing", "Unicorn Model", "Breaker Block Reversal", "Mitigation Block Entry", "Inversion FVG Reversal", "NY AM Session Reversal", "Liquidity Void Fill", "Market Maker Buy Model", "Venom Model", "Smart Money Reversal", "Power of Three Daily Bias", "Weekly Profile", "Quarterly Theory Reversal"]) swingLeft = input.int(2, "Swing Lookback (left/right bars)", minval=1) eqTolPct = input.float(0.1, "Liquidity Pool Tolerance (%)", minval=0.0) / 100 kzStartH = input.int(10, "Killzone Start Hour (NY time)", minval=0, maxval=23) kzEndH = input.int(11, "Killzone End Hour (NY time)", minval=0, maxval=23) showZones = input.bool(true, "Draw order block / FVG zones") // ── Types (mirrors Python's Swing / Signal dataclasses) ───────────────── type Signal string direction float entry float stop float target string note // ── Persistent swing history (Python's find_swings, via native pivots) ── var array swHighPrice = array.new_float() var array swLowPrice = array.new_float() ph = ta.pivothigh(high, swingLeft, swingLeft) pl = ta.pivotlow(low, swingLeft, swingLeft) if not na(ph) array.push(swHighPrice, ph) if not na(pl) array.push(swLowPrice, pl) // ── Structure labeling — HH/HL/LH/LL + BOS/CHoCH (Python label_structure) ─ var float lastHigh = na var float lastLow = na var string trendState = na var string lastBreak = na // "BOS" or "CHoCH", set the bar a swing confirms lastBreak := na if not na(ph) label1 = na(lastHigh) ? "H" : (ph > lastHigh ? "HH" : "LH") if trendState == "up" and label1 == "LH" lastBreak := "CHoCH" trendState := "down" else if trendState == "up" and label1 == "HH" lastBreak := "BOS" else if na(trendState) and label1 == "HH" trendState := "up" lastHigh := ph if not na(pl) label2 = na(lastLow) ? "L" : (pl > lastLow ? "HL" : "LL") if trendState == "down" and label2 == "HL" lastBreak := "CHoCH" trendState := "up" else if trendState == "down" and label2 == "LL" lastBreak := "BOS" else if na(trendState) and label2 == "LL" trendState := "down" lastLow := pl // ── Liquidity pools — cluster swings within eqTolPct (Python find_liquidity_pools) ─ poolPrice(array prices, float tol) => float result = na n = array.size(prices) if n > 0 float p0 = array.get(prices, n - 1) float sum = p0 int cnt = 1 if n >= 2 for i = n - 2 to 0 float pi = array.get(prices, i) if math.abs(pi - p0) / p0 <= tol sum += pi cnt += 1 else break result := sum / cnt result lowPoolPrice = poolPrice(swLowPrice, eqTolPct) highPoolPrice = poolPrice(swHighPrice, eqTolPct) // ── Sweep detection — trades through the pool then closes back (Python detect_sweep) ─ sweptLow = not na(lowPoolPrice) and low < lowPoolPrice and close > lowPoolPrice sweptHigh = not na(highPoolPrice) and high > highPoolPrice and close < highPoolPrice // ── Order block — last opposite candle before a break (Python find_order_block) ─ bullishOB(int lookback) => float obLow = na float obHigh = na for i = 1 to lookback if close[i] < open[i] obLow := low[i] obHigh := high[i] break [obLow, obHigh] [obLowBull, obHighBull] = bullishOB(20) // This port only wires up the bullish/long side of each strategy for clarity — // a bearishOB() mirror is the same 6-line function with close[i] > open[i], and every // short-side condition below (Breaker, Inversion FVG) is built directly from it inline. // ── Fair Value Gap — 3-candle wick gap (Python find_fvg; native Pine idiom) ─ // Bullish-side only, matching the long-only simplification noted above — // a bearish FVG is the mirror condition: high < low[2]. bullFVG = low > high[2] bullFVGLow = high[2] bullFVGHigh = low // ── Premium/Discount + OTE band (Python premium_discount_zone) ─────────── dealingHigh = array.size(swHighPrice) > 0 ? array.max(swHighPrice) : na dealingLow = array.size(swLowPrice) > 0 ? array.min(swLowPrice) : na midpoint = (dealingHigh + dealingLow) / 2 oteHigh = dealingHigh - (dealingHigh - dealingLow) * 0.62 oteLow = dealingHigh - (dealingHigh - dealingLow) * 0.79 // ── Killzone — native time functions beat the Python string-parsing hack ─ nyHour = hour(time, "America/New_York") inKillzone = nyHour >= kzStartH and nyHour < kzEndH // ═══════════════════════════════════════════════════════════════════════ // Tier 1 — Highly Mechanical // ═══════════════════════════════════════════════════════════════════════ // OTE + Order Block Confluence: bullish OB overlaps the 62-79% OTE band oteObOverlap = not na(obLowBull) and not na(oteHigh) and math.max(obLowBull, oteLow) <= math.min(obHighBull, oteHigh) oteObSignal = oteObOverlap and low <= obHighBull and close > obLowBull // Break-and-Retest: BOS confirmed, then price retests the broken level bosLevel = lastBreak == "BOS" ? (trendState == "up" ? lastHigh : lastLow) : na breakRetestSignal = not na(bosLevel) and low <= bosLevel and high >= bosLevel and close > bosLevel // Turtle Soup: false breakout of a prior low that reverses same/next bar turtleSoupSignal = low < ta.lowest(low, 20)[2] and close > ta.lowest(low, 20)[2] // Silver Bullet: FVG forms inside the killzone silverBulletSignal = bullFVG and inKillzone // 2022 Model: sweep of old low -> CHoCH -> entry on the retracement FVG model2022Signal = sweptLow and lastBreak == "CHoCH" and bullFVG // ═══════════════════════════════════════════════════════════════════════ // Tier 2 — Moderately Precise // ═══════════════════════════════════════════════════════════════════════ // Judas Swing: early false move at session open sweeps liquidity, reverses judasSwingSignal = sweptLow and close > open[2] // Unicorn Model: breaker block + FVG overlap unicornSignal = lastBreak == "CHoCH" and not na(obLowBull) and bullFVG and math.max(obLowBull, bullFVGLow) <= math.min(obHighBull, bullFVGHigh) // Breaker Block Reversal: failed bullish OB retested from above, rejects obFailed = not na(obLowBull) and close < obLowBull breakerRevSignal = obFailed[1] and high >= obLowBull[1] and high <= obHighBull[1] and close < obLowBull[1] // Mitigation Block Entry: narrow pre-launch consolidation retest launchCandle = (close - open) > 2 * (high[1] - low[1]) mitigationSignal = launchCandle[1] and low <= high[2] and low >= low[2] and close > low[2] // Inversion FVG Reversal: bullish FVG closed through completely, then flips fvgInverted = bullFVG[3] and close < bullFVGLow[3] inversionFvgSignal = fvgInverted and high >= bullFVGLow[3] and high <= bullFVGHigh[3] and close < bullFVGLow[3] // NY AM Session Reversal: sweep-and-reverse, filtered to the killzone only nyAmSignal = sweptLow and inKillzone // Liquidity Void Fill: thin/fast candle's range gets traded through quickly voidRange = high[2] - low[2] > 0 ? high[2] - low[2] : 1e-9 voidBodyPct = math.abs(close[2] - open[2]) / voidRange voidCandle = voidBodyPct >= 1 / 2.5 // mostly-body candle, little wick either side voidFillSignal = voidCandle and low <= math.max(open[2], close[2]) and low >= math.min(open[2], close[2]) // ═══════════════════════════════════════════════════════════════════════ // Tier 3 — Conceptual / Discretionary // (these compute a BIAS, not a hard signal — matching Lesson 11's honesty) // ═══════════════════════════════════════════════════════════════════════ // Market Maker Buy Model: accumulation range swept, then reclaimed (AMD) accHigh15 = ta.highest(high, 5)[10] accLow15 = ta.lowest(low, 5)[10] mmbmSwept = ta.lowest(low, 5)[5] < accLow15 mmbmSignal = mmbmSwept and close > accHigh15 // Venom Model: liquidity run + FVG entry, no CHoCH required (looser by design) venomSignal = (ta.lowest(low, 5) < ta.lowest(low, 5)[5]) and bullFVG and low <= bullFVGHigh and low >= bullFVGLow // Smart Money Reversal: sweep + ANY structure shift, no confluence at all smrSignal = (sweptLow or sweptHigh) and (lastBreak == "BOS" or lastBreak == "CHoCH") // Power of Three Daily Bias: bias only, not a trigger poThreeAccHigh = ta.highest(high, 8)[16] poThreeAccLow = ta.lowest(low, 8)[16] poThreeSweptLow = ta.lowest(low, 8)[8] < poThreeAccLow poThreeBias = poThreeSweptLow and close > poThreeAccHigh ? "bullish" : (not poThreeSweptLow ? "bearish" : "unclear") // Weekly Profile: this week's range vs prior week's high/low priorWeekHigh = request.security(syminfo.tickerid, "W", high[1], lookahead=barmerge.lookahead_off) priorWeekLow = request.security(syminfo.tickerid, "W", low[1], lookahead=barmerge.lookahead_off) weeklySweptLow = low < priorWeekLow weeklyBrokeHigh = high > priorWeekHigh weeklyProfileBias = weeklySweptLow and weeklyBrokeHigh ? "bullish" : (weeklyBrokeHigh ? "bearish" : "mixed") // Quarterly Theory Reversal: reversal near a Q4 (final-quarter) boundary qSize = 20 // bars per quarter — adjust per your own convention, not standardized q1Range = high[qSize * 4 - 1] - low[qSize * 4 - 1] quarterlyReversalSignal = (close - open) > q1Range and close > open and bar_index % (qSize * 4) >= qSize * 3 // ═══════════════════════════════════════════════════════════════════════ // Selector — route the chosen strategy to entries + zone drawing // ═══════════════════════════════════════════════════════════════════════ bool longCondition = switch strategySelect "OTE + Order Block Confluence" => oteObSignal "Break-and-Retest" => breakRetestSignal "Turtle Soup" => turtleSoupSignal "Silver Bullet" => silverBulletSignal "2022 Model" => model2022Signal "Judas Swing" => judasSwingSignal "Unicorn Model" => unicornSignal "Mitigation Block Entry" => mitigationSignal "NY AM Session Reversal" => nyAmSignal "Liquidity Void Fill" => voidFillSignal "Market Maker Buy Model" => mmbmSignal "Venom Model" => venomSignal "Smart Money Reversal" => smrSignal "Quarterly Theory Reversal" => quarterlyReversalSignal => false // Breaker/InversionFVG are short setups; Power of Three/Weekly Profile are bias-only — see notes below bool shortCondition = switch strategySelect "Breaker Block Reversal" => breakerRevSignal "Inversion FVG Reversal" => inversionFvgSignal => false if longCondition strategy.entry("Long", strategy.long) sigLong = Signal.new("long", close, low[1], na, strategySelect) label.new(bar_index, low, "▲ " + sigLong.direction + " @ " + str.tostring(sigLong.entry, format.mintick) + "\nstop " + str.tostring(sigLong.stop, format.mintick), style=label.style_label_up, color=color.new(color.green, 0), textcolor=color.white, size=size.small) if shortCondition strategy.entry("Short", strategy.short) sigShort = Signal.new("short", close, high[1], na, strategySelect) label.new(bar_index, high, "▼ " + sigShort.direction + " @ " + str.tostring(sigShort.entry, format.mintick) + "\nstop " + str.tostring(sigShort.stop, format.mintick), style=label.style_label_down, color=color.new(color.red, 0), textcolor=color.white, size=size.small) // Power of Three and Weekly Profile intentionally have no strategy.entry() // call — they're bias frameworks, not triggers, exactly as Lesson 11 ranks // them (Quarterly Theory Reversal, by contrast, does define a hard entry in // both the Python and Pine ports — see the switch above). Plot the two // bias-only frameworks as labels instead of faking a signal for them: if strategySelect == "Power of Three Daily Bias" and barstate.islast label.new(bar_index, high, "PO3 bias: " + poThreeBias, style=label.style_label_down, color=color.new(color.orange, 0)) if strategySelect == "Weekly Profile" and barstate.islast label.new(bar_index, high, "Weekly bias: " + weeklyProfileBias, style=label.style_label_down, color=color.new(color.gray, 0)) // ── Zone drawing (order block / FVG) for the currently selected strategy ─ if showZones and not na(obLowBull) and (strategySelect == "OTE + Order Block Confluence" or strategySelect == "Unicorn Model" or strategySelect == "Breaker Block Reversal") box.new(bar_index - 20, obHighBull, bar_index, obLowBull, border_color=color.blue, bgcolor=color.new(color.blue, 85)) if showZones and bullFVG box.new(bar_index - 2, bullFVGHigh, bar_index, bullFVGLow, border_color=color.purple, bgcolor=color.new(color.purple, 88)) plotshape(longCondition, title="Long Entry", style=shape.triangleup, location=location.belowbar, color=color.new(color.green, 0), size=size.small) plotshape(shortCondition, title="Short Entry", style=shape.triangledown, location=location.abovebar, color=color.new(color.red, 0), size=size.small)