//@version=5 strategy("4-Hour Range Scalper Strategy [Optimized]", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=10) // --- INPUTS --- i_rr = input.float(2.0, title="Risk-to-Reward Ratio", group="Risk Management") i_ny_tz = input.string("America/New_York", title="Session Time Zone", group="Session Settings") i_session = input.session("0000-0400", title="First 4H Candle Session (NY Time)", group="Session Settings") // --- SESSION & MULTI-TIMEFRAME LOGIC --- // Check if current bar is within the designated first 4-hour window of the day (New York time) in_first_candle = not na(time(timeframe.period, i_session + ":1234567", i_ny_tz)) is_new_session = ta.change(time("D", i_ny_tz)) != 0 // Variables to store the active day's range var float r_high = na var float r_low = na // Temporary variables to capture the high/low during the first 4-hour block var float temp_high = na var float temp_low = na if (is_new_session) temp_high := na temp_low := na r_high := na r_low := na if (in_first_candle) temp_high := na(temp_high) ? high : math.max(temp_high, high) temp_low := na(temp_low) ? low : math.min(temp_low, low) r_high := temp_high r_low := temp_low else // Lock values after the first session candle closes if (not na(temp_high) and na(r_high)) r_high := temp_high r_low := temp_low // Persistent range lines across the day var float active_high = na var float active_low = na if (is_new_session) active_high := na active_low := na if (not na(r_high)) active_high := r_high active_low := r_low // --- PLOTS --- plot(active_high, title="4H Range High", color=color.red, style=plot.style_linebr, linewidth=2) plot(active_low, title="4H Range Low", color=color.green, style=plot.style_linebr, linewidth=2) // --- EXECUTION LOGIC --- bool can_trade = strategy.position_size == 0 var bool broke_above = false var bool broke_below = false // Reset breakout flags on a new trading day if (is_new_session) broke_above := false broke_below := false // Track breakouts (candle fully closes outside, or wick breaches) if (not na(active_high) and high > active_high) broke_above := true if (not na(active_low) and low < active_low) broke_below := true // Short Entry Trigger: Price broke above 4H high, now closing back inside bool trigger_short = broke_above and not na(active_high) and (close < active_high) and (close[1] >= active_high) if (can_trade and trigger_short) float entry_price = close float stop_loss = ta.highest(high, 5) // Recent swing high fallback float risk = stop_loss - entry_price float target = entry_price - (risk * i_rr) if (risk > 0) strategy.entry("Short Re-entry", strategy.short) strategy.exit("TP/SL Short", "Short Re-entry", stop=stop_loss, limit=target) broke_above := false // Long Entry Trigger: Price broke below 4H low, now closing back inside bool trigger_long = broke_below and not na(active_low) and (close > active_low) and (close[1] <= active_low) if (can_trade and trigger_long) float entry_price = close float stop_loss = ta.lowest(low, 5) // Recent swing low fallback float risk = entry_price - stop_loss float target = entry_price + (risk * i_rr) if (risk > 0) strategy.entry("Long Re-entry", strategy.long) strategy.exit("TP/SL Long", "Long Re-entry", stop=stop_loss, limit=target) broke_below := false