SMC 3-Step Strategy [A+ Setup] V6
This is a complete Smart Money Concepts (SMC) strategy that combines Daily Bias, Intraday Structure, and Liquidity Sweeps into a mechanical "A+ Setup".
Strategy Logic
The strategy follows a strict 3-step process to validate entries:
- Daily Bias: Checks if the previous day closed higher/lower than it opened.
- Intraday Structure: Confirms trend alignment on the M15 timeframe (Non-Repainting).
- Liquidity Sweep: Waits for a sweep of Asia Session High/Low followed by a Change of Character (ChoCh).
Pine Script V6 Code
Copy the code below and paste it into your TradingView Pine Editor.
//@version=6
strategy("SMC 3-Step Strategy [A+ Setup] Non-Repainting", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=1, currency=currency.USD)
// =============================================================================
// 1. INPUTS
// =============================================================================
grp_time = "Session Times (NY UTC-5)"
asia_sess = input.session("1900-0000", "Asian Session", group=grp_time) // Pre-London
killzone = input.session("0200-1100", "Trading Killzone (Lon/NY)", group=grp_time) // Execution window
grp_struc = "Structure Settings"
m15_len = input.int(5, "M15 Swing Length", minval=1, group=grp_struc, tooltip="Length to define swing points on M15")
entry_len = input.int(3, "Entry Chart Swing Length", minval=1, group=grp_struc, tooltip="Length to define ChoCh on current timeframe")
grp_risk = "Risk Management"
rr_ratio = input.float(5.0, "Risk:Reward Ratio", step=0.5, group=grp_risk)
use_fixed_sl= input.bool(false, "Use Fixed Pips SL?", group=grp_risk)
sl_pips = input.float(10.0, "Fixed SL (Pips)", group=grp_risk)
// =============================================================================
// 2. STEP 1: DAILY BIAS
// =============================================================================
// Get Daily Open and Close.
// We use [1] and lookahead=on to ensure we are referencing the COMPLETED previous day.
d_open = request.security(syminfo.tickerid, "D", open[1], lookahead=barmerge.lookahead_on)
d_close = request.security(syminfo.tickerid, "D", close[1], lookahead=barmerge.lookahead_on)
// Determine Bias
daily_bullish = d_close > d_open
daily_bearish = d_close < d_open
// Visuals for Step 1
plotshape(daily_bullish, "Daily Bull", shape.triangleup, location.top, color.green, size=size.tiny)
plotshape(daily_bearish, "Daily Bear", shape.triangledown, location.bottom, color.red, size=size.tiny)
// =============================================================================
// 3. STEP 2: INTRADAY BIAS (M15 STRUCTURE) - NON-REPAINTING
// =============================================================================
// Structure calculation function
calc_structure(len) =>
float ph = ta.pivothigh(high, len, len)
float pl = ta.pivotlow(low, len, len)
var int trend = 0 // 1 = Bullish, -1 = Bearish
var float last_ph = high
var float last_pl = low
if not na(ph)
last_ph := ph
if not na(pl)
last_pl := pl
// Break of Structure Logic
if close > last_ph
trend := 1
if close < last_pl
trend := -1
trend
// Request M15 structure data.
// CRITICAL FIX: We request 'calc_structure(m15_len)[1]'.
// The [1] ensures we get the value of the PREVIOUSLY CLOSED M15 bar.
// This eliminates the repainting risk identified by the AI.
m15_trend_confirmed = request.security(syminfo.tickerid, "15", calc_structure(m15_len)[1], lookahead=barmerge.lookahead_on)
// Visual verification of Alignment (Daily Bias + Intraday Bias)
bias_aligned_bull = daily_bullish and m15_trend_confirmed == 1
bias_aligned_bear = daily_bearish and m15_trend_confirmed == -1
// Background color to show valid trading days/times
bgcolor(bias_aligned_bull ? color.new(color.green, 90) : na, title="Bullish Alignment Background")
bgcolor(bias_aligned_bear ? color.new(color.red, 90) : na, title="Bearish Alignment Background")
// =============================================================================
// 4. STEP 3: LIQUIDITY SWEEP (ASIA SESSION)
// =============================================================================
// Define time zone
t_zone = "America/New_York"
// Check time windows
in_asia = time(timeframe.period, asia_sess, t_zone)
in_killzone = time(timeframe.period, killzone, t_zone)
// Variables to store Asia High/Low
var float asia_h = na
var float asia_l = na
// [FIX] Strict boolean check for new day
bool is_new_day = ta.change(time("D")) != 0
// Reset Asia High/Low at the start of a new day
if is_new_day
asia_h := na
asia_l := na
// Track High/Low during Asia Session
if not na(in_asia)
asia_h := na(asia_h) ? high : math.max(asia_h, high)
asia_l := na(asia_l) ? low : math.min(asia_l, low)
// Plot Asia Range
plot(not na(in_asia) or not na(in_killzone) ? asia_h : na, "Asia High", color.red, style=plot.style_linebr)
plot(not na(in_asia) or not na(in_killzone) ? asia_l : na, "Asia Low", color.green, style=plot.style_linebr)
// Detect Sweep Logic
// Bullish Setup: Bias is Bullish + Price sweeps BELOW Asia Low
sweep_low_cond = bias_aligned_bull and not na(in_killzone) and low < asia_l
// Bearish Setup: Bias is Bearish + Price sweeps ABOVE Asia High
sweep_high_cond = bias_aligned_bear and not na(in_killzone) and high > asia_h
// State management for Sweep (Latch mechanism)
var bool swept_asia_low = false
var bool swept_asia_high = false
if is_new_day
swept_asia_low := false
swept_asia_high := false
if sweep_low_cond
swept_asia_low := true
if sweep_high_cond
swept_asia_high := true
// =============================================================================
// 5. ENTRY TRIGGER (CHOCH / STRUCTURE SHIFT)
// =============================================================================
// Calculate local pivots on the CURRENT timeframe (e.g. M5)
l_ph = ta.pivothigh(high, entry_len, entry_len)
l_pl = ta.pivotlow(low, entry_len, entry_len)
var float entry_swing_high = high
var float entry_swing_low = low
if not na(l_ph)
entry_swing_high := l_ph
if not na(l_pl)
entry_swing_low := l_pl
// [FIX] Calculate crossovers globally to ensure consistent execution history
bull_break_confirmed = ta.crossover(close, entry_swing_high)
bear_break_confirmed = ta.crossunder(close, entry_swing_low)
// -----------------------------------------------------------------------------
// LONG ENTRY EXECUTION
// -----------------------------------------------------------------------------
// 1. Daily & Intraday Bias are Bullish
// 2. We have swept the Asia Low
// 3. We get a Candle Close ABOVE the recent local High (ChoCh)
long_trigger = bias_aligned_bull and swept_asia_low and bull_break_confirmed and strategy.position_size == 0
if long_trigger
// Stop Loss calculation
float sl_price = use_fixed_sl ? close - (sl_pips * syminfo.mintick * 10) : entry_swing_low
float risk = close - sl_price
float tp_price = close + (risk * rr_ratio)
if risk > 0
strategy.entry("Long A+", strategy.long)
strategy.exit("Exit Long", "Long A+", stop=sl_price, limit=tp_price)
swept_asia_low := false // Reset flag to prevent reentry on same sweep
// -----------------------------------------------------------------------------
// SHORT ENTRY EXECUTION
// -----------------------------------------------------------------------------
// 1. Daily & Intraday Bias are Bearish
// 2. We have swept the Asia High
// 3. We get a Candle Close BELOW the recent local Low (ChoCh)
short_trigger = bias_aligned_bear and swept_asia_high and bear_break_confirmed and strategy.position_size == 0
if short_trigger
// Stop Loss calculation
float sl_price = use_fixed_sl ? close + (sl_pips * syminfo.mintick * 10) : entry_swing_high
float risk = sl_price - close
float tp_price = close - (risk * rr_ratio)
if risk > 0
strategy.entry("Short A+", strategy.short)
strategy.exit("Exit Short", "Short A+", stop=sl_price, limit=tp_price)
swept_asia_high := false // Reset flag
// =============================================================================
// VISUALIZATION
// =============================================================================
plot(entry_swing_high, "Entry Structure High", color.new(color.blue, 50))
plot(entry_swing_low, "Entry Structure Low", color.new(color.blue, 50))
// [FIX] Used named argument 'textcolor' to fix syntax error
plotshape(long_trigger, "Long Entry", shape.labelup, location.belowbar, color.green, text="BUY", textcolor=color.white)
plotshape(short_trigger, "Short Entry", shape.labeldown, location.abovebar, color.red, text="SELL", textcolor=color.white)
How to Optimize This Strategy
Raw strategies often fail due to slippage and lack of dynamic risk management. To make this strategy production-ready:
- Add Commission Logic: Most backtests ignore fees.
- Implement Dynamic Stops: Use ATR-based trailing stops.
- Filter Choppy Markets: Add an ADX or Volume filter.
You can do all of this automatically using our AI Co-pilot.