//@version=6
strategy("Hierarchical Trading System v6 (Fakeout Protected)", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=10)
// ==========================================
// --- INPUTS ---
// ==========================================
// 1. Regime Classifier Inputs (Layer 1)
adxLength = input.int(14, title="ADX Length", group="Layer 1: Regime Classifier")
adxThreshold = input.int(25, title="ADX Threshold", group="Layer 1: Regime Classifier")
cooldownBars = input.int(5, title="Cooldown Bars", minval=0, group="Execution Settings")
// 2. Mean Reversion Inputs (Layer 2 - Sub-Strategy A)
bbLength = input.int(20, title="BB Length", group="Sub-Strategy A: Mean Reversion")
baseMult = input.float(2.5, title="Base BB Multiplier", group="Sub-Strategy A: Mean Reversion")
asymOffset = input.float(0.5, title="Asymmetric Offset", group="Sub-Strategy A: Mean Reversion")
emaLength = input.int(200, title="Trend Filter EMA", group="Sub-Strategy A: Mean Reversion")
// 3. Trend Following Inputs (Layer 2 - Sub-Strategy B)
dcLength = input.int(20, title="Donchian Breakout Length", group="Sub-Strategy B: Trend Following")
dcExitLength = input.int(10, title="Donchian Exit Length", group="Sub-Strategy B: Trend Following")
// 4. Fakeout Filters (Sub-Strategy B Additions)
useVolumeFilter = input.bool(true, title="Enable Volume Confirmation?", group="Sub-Strategy B: Breakout Filters", tooltip="Breakout volume must exceed average volume")
volLength = input.int(20, title="Volume Average Length", group="Sub-Strategy B: Breakout Filters")
volMultiplier = input.float(1.5, title="Volume Multiplier (x SMA)", group="Sub-Strategy B: Breakout Filters")
useAtrFilter = input.bool(true, title="Enable Range (ATR) Confirmation?", group="Sub-Strategy B: Breakout Filters", tooltip="Breakout candle range must exceed ATR")
atrLength = input.int(14, title="ATR Length", group="Sub-Strategy B: Breakout Filters")
atrMultiplier = input.float(1.0, title="Range Multiplier (x ATR)", group="Sub-Strategy B: Breakout Filters")
// --- NEW DEFENSIVE BREAKOUT FILTERS ---
useWickFilter = input.bool(true, title="Enable Rejection Wick Filter?", group="Sub-Strategy B: Breakout Filters", tooltip="Breakout candle rejection wick cannot exceed threshold")
maxWickPct = input.float(35.0, title="Max Rejection Wick %", group="Sub-Strategy B: Breakout Filters", tooltip="Max rejection wick size as a percentage of total candle range")
useAtrPenetration = input.bool(true, title="Enable ATR Penetration Filter?", group="Sub-Strategy B: Breakout Filters", tooltip="Close must exceed breakout level by a minimum distance")
atrPenetrationMult = input.float(0.5, title="Min ATR Penetration Multiplier", group="Sub-Strategy B: Breakout Filters", tooltip="Multiplier of ATR to determine clearance over breakout level")
// ==========================================
// --- CALCULATIONS & REGIME CLASS ---
// ==========================================
// Layer 1: ADX Regime Calculation
[diPlus, diMinus, adxValue] = ta.dmi(adxLength, adxLength)
bool isTrending = adxValue >= adxThreshold
bool isRanging = not isTrending
// Color background based on active regime: Teal for Trending, Orange for Ranging
bgcolor(isTrending ? color.new(color.teal, 98) : color.new(color.orange, 98), title="Regime Background Color")
// Sub-Strategy A: Asymmetric Bollinger Bands
basis = ta.sma(close, bbLength)
stdDevVal = ta.stdev(close, bbLength)
trendEma = ta.ema(close, emaLength)
bool isUptrend = close > trendEma
float longMult = isUptrend ? (baseMult - asymOffset) : (baseMult + asymOffset)
float shortMult = isUptrend ? (baseMult + asymOffset) : (baseMult - asymOffset)
upperBB = basis + (shortMult * stdDevVal)
lowerBB = basis - (longMult * stdDevVal)
// Sub-Strategy B: Donchian Channels
dcUpper = ta.highest(high, dcLength)[1]
dcLower = ta.lowest(low, dcLength)[1]
dcExitUpper = ta.highest(high, dcExitLength)[1]
dcExitLower = ta.lowest(low, dcExitLength)[1]
// ==========================================
// --- FAKEOUT FILTER LOGIC ---
// ==========================================
// 1. Volume Confirmation
volMa = ta.sma(volume, volLength)
bool isVolumeConfirmed = not useVolumeFilter or (volume > (volMa * volMultiplier))
// 2. Range Expansion Confirmation
atrVal = ta.atr(atrLength)
candleRange = high - low
bool isRangeConfirmed = not useAtrFilter or (candleRange > (atrVal * atrMultiplier))
// 3. NEW: Rejection Wick Ratio Filter (Prevents entering on immediate rejections)
upperWick = high - math.max(open, close)
lowerWick = math.min(open, close) - low
bool longWickOK = not useWickFilter or (candleRange > 0 ? (upperWick / candleRange) * 100 <= maxWickPct : true)
bool shortWickOK = not useWickFilter or (candleRange > 0 ? (lowerWick / candleRange) * 100 <= maxWickPct : true)
// 4. NEW: ATR Penetration Filter (Ensures the close cleanly clears the channel boundary)
bool longAtrPenetration = not useAtrPenetration or ((close - dcUpper) >= (atrVal * atrPenetrationMult))
bool shortAtrPenetration = not useAtrPenetration or ((dcLower - close) >= (atrVal * atrPenetrationMult))
// Combined Directional Breakout Validation Pipelines
bool isLongBreakoutValid = isVolumeConfirmed and isRangeConfirmed and longWickOK and longAtrPenetration
bool isShortBreakoutValid = isVolumeConfirmed and isRangeConfirmed and shortWickOK and shortAtrPenetration
// ==========================================
// --- SIGNALS & COOLDOWN ---
// ==========================================
var int lastSignalBar = -99999
bool isCooldownOver = (bar_index - lastSignalBar) >= cooldownBars
// Raw signals
bool rawMrLong = ta.crossover(close, lowerBB)
bool rawMrShort = ta.crossunder(close, upperBB)
bool rawTfLong = ta.crossover(close, dcUpper)
bool rawTfShort = ta.crossunder(close, dcLower)
// Filtered signals based on current Regime State
bool mrLongCondition = isRanging and rawMrLong and isCooldownOver
bool mrShortCondition = isRanging and rawMrShort and isCooldownOver
// Trend-Following Signals must pass the direction-specific Breakout Validation Filters
bool tfLongCondition = isTrending and rawTfLong and isCooldownOver and isLongBreakoutValid
bool tfShortCondition = isTrending and rawTfShort and isCooldownOver and isShortBreakoutValid
// Update Cooldown Tracker on any executed signal
if mrLongCondition or mrShortCondition or tfLongCondition or tfShortCondition
lastSignalBar := bar_index
// ==========================================
// --- ALERT MESSAGE BUILDERS ---
// ==========================================
// FIX: the original script had zero alertcondition()/alert()/alert_message
// calls anywhere -- that is why entries plotted on the chart but no alert
// ever fired. There was nothing wired to trigger one. Every message below
// identifies which of the four entry types (or which exit) fired, plus
// ticker/timeframe/price, so a single "Any alert() function call" alert
// created on this script tells you exactly what happened without opening
// the chart.
//
// STANDARD ALERT FORMAT (apply to every future script's alerts the same
// way): every message leads with an ALL-CAPS type tag stating the
// direction up front -- "BULLISH ENTRY" / "BEARISH ENTRY" for entries,
// "LONG EXIT" / "SHORT EXIT" for exits -- so the notification itself
// (phone lock screen, webhook payload, whatever reads it) says which way
// the signal is without needing to open the chart or parse a strategy-
// specific label. Everything after that tag is context: which
// sub-strategy/kind fired, then ticker, timeframe, and price.
f_alertMsg(string kind, string label, float px) =>
kind + " | " + label + " | " + syminfo.ticker + " " + timeframe.period + " @ " + str.tostring(px, format.mintick)
// ==========================================
// --- EXECUTION ENGINE ---
// ==========================================
// 1. Mean Reversion Execution (MR)
if mrLongCondition
string msg = f_alertMsg("BULLISH ENTRY", "MR (mean reversion)", close)
strategy.entry("MR Long", strategy.long, comment="MR Buy", alert_message=msg)
alert(msg, alert.freq_once_per_bar_close)
if mrShortCondition
string msg = f_alertMsg("BEARISH ENTRY", "MR (mean reversion)", close)
strategy.entry("MR Short", strategy.short, comment="MR Short", alert_message=msg)
alert(msg, alert.freq_once_per_bar_close)
// 2. Trend Following Execution (TF)
if tfLongCondition
string msg = f_alertMsg("BULLISH ENTRY", "TF (breakout)", close)
strategy.entry("TF Long", strategy.long, comment="TF Breakout Buy", alert_message=msg)
alert(msg, alert.freq_once_per_bar_close)
if tfShortCondition
string msg = f_alertMsg("BEARISH ENTRY", "TF (breakout)", close)
strategy.entry("TF Short", strategy.short, comment="TF Breakout Short", alert_message=msg)
alert(msg, alert.freq_once_per_bar_close)
// ==========================================
// --- EXIT ENGINE ---
// ==========================================
// MR Exits (Reversion to Mean)
if isRanging
if ta.crossover(close, basis) and (strategy.position_size < 0)
string msg = f_alertMsg("SHORT EXIT", "MR cover (reverted to mean)", close)
strategy.close("MR Short", comment="MR Short Cover", alert_message=msg)
alert(msg, alert.freq_once_per_bar_close)
if ta.crossunder(close, basis) and (strategy.position_size > 0)
string msg = f_alertMsg("LONG EXIT", "MR sell (reverted to mean)", close)
strategy.close("MR Long", comment="MR Long Sell", alert_message=msg)
alert(msg, alert.freq_once_per_bar_close)
// TF Exits (Trailing Highs/Lows)
if isTrending
if ta.crossunder(close, dcExitLower) and (strategy.position_size > 0)
string msg = f_alertMsg("LONG EXIT", "TF trailing stop", close)
strategy.close("TF Long", comment="TF Trail Exit", alert_message=msg)
alert(msg, alert.freq_once_per_bar_close)
if ta.crossover(close, dcExitUpper) and (strategy.position_size < 0)
string msg = f_alertMsg("SHORT EXIT", "TF trailing stop", close)
strategy.close("TF Short", comment="TF Trail Exit", alert_message=msg)
alert(msg, alert.freq_once_per_bar_close)
// ==========================================
// --- VISUALIZATIONS & ALERTS ---
// ==========================================
plot(basis, color=color.new(color.blue, 50), title="BB Basis (Mean)")
plot(trendEma, color=color.orange, linewidth=2, title="Trend Filter EMA")
plotshape(mrLongCondition, title="MR Long Signal", style=shape.triangleup, location=location.belowbar, color=color.green, size=size.small, text="MR")
plotshape(mrShortCondition, title="MR Short Signal", style=shape.triangledown, location=location.abovebar, color=color.red, size=size.small, text="MR")
plotshape(tfLongCondition, title="TF Long Signal", style=shape.triangleup, location=location.belowbar, color=color.teal, size=size.small, text="TF Breakout")
plotshape(tfShortCondition, title="TF Short Signal", style=shape.triangledown, location=location.abovebar, color=color.maroon, size=size.small, text="TF Breakout")
// alertcondition() gives a second, independent way to pick an alert on
// this script from the "Condition" dropdown (rather than "Any alert()
// function call") -- pick whichever workflow you prefer in the Create
// Alert dialog; both are wired to fire on the same bars.
alertcondition(mrLongCondition, title="MR Long Entry", message="BULLISH ENTRY | MR (mean reversion) | {{ticker}} {{interval}} @ {{close}}")
alertcondition(mrShortCondition, title="MR Short Entry", message="BEARISH ENTRY | MR (mean reversion) | {{ticker}} {{interval}} @ {{close}}")
alertcondition(tfLongCondition, title="TF Long Entry", message="BULLISH ENTRY | TF (breakout) | {{ticker}} {{interval}} @ {{close}}")
alertcondition(tfShortCondition, title="TF Short Entry", message="BEARISH ENTRY | TF (breakout) | {{ticker}} {{interval}} @ {{close}}")
Overview
In ranging conditions it fades asymmetric Bollinger Band extremes with a 200 EMA trend filter. In trending conditions it trades Donchian channel breakouts, protected by optional volume, candle range, rejection wick and ATR penetration filters. Exits use a Donchian exit channel and a cooldown applies after trades. Background colour shows the regime, size is a percent of equity, and no stop loss is set.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
ADX Length
int
14
adxLength
ADX Threshold
int
25
adxThreshold
Cooldown Bars
int
5
cooldownBars
BB Length
int
20
bbLength
Base BB Multiplier
float
2.5
baseMult
Asymmetric Offset
float
0.5
asymOffset
Trend Filter EMA
int
200
emaLength
Donchian Breakout Length
int
20
dcLength
Donchian Exit Length
int
10
dcExitLength
Enable Volume Confirmation?
bool
true
useVolumeFilter
Volume Average Length
int
20
volLength
Volume Multiplier (x SMA)
float
1.5
volMultiplier
Show all 19 settings
Setting
Type
Default
Variable
Enable Range (ATR) Confirmation?
bool
true
useAtrFilter
ATR Length
int
14
atrLength
Range Multiplier (x ATR)
float
1.0
atrMultiplier
Enable Rejection Wick Filter?
bool
true
useWickFilter
Max Rejection Wick %
float
35.0
maxWickPct
Enable ATR Penetration Filter?
bool
true
useAtrPenetration
Min ATR Penetration Multiplier
float
0.5
atrPenetrationMult
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.
The Chained Linear Regression Reversal Strategy plots linear regression channels with upper and lower standard deviation bands directly on the price chart across a user-defined time window. When price breaks out of the static channel for a confirmed number of
Traiversal A001 is a breakout reversal strategy designed primarily for cryptocurrency trading. It identifies reversal entry opportunities three candles following a breakout and closes positions when a breakout in the opposite direction occurs. The script inclu
RG Structure v2.0 [Visual Edition] is a strategy that identifies pivot points over a lookback window to construct trendlines. It evaluates breaks and retests of these trendlines using scoring weights, violation penalties, and regime detection to generate entry
This strategy operates directly on the price chart to generate trading signals across four switchable modules: trend following, mean reversion, momentum breakout, and smart money concepts. It triggers trade entries when a user-defined minimum number of modules
Sapphire Fibonacci Strategies is a multi-mode strategy that combines Momentum Breakout, Mean Reversion, and Fibonacci Retracement models built on Fibonacci-period moving averages. It generates long and short trade signals based on price crossovers and moving a
This overlay strategy combines an AlphaTrend core with kinematic, Bayesian, and mean-reversion models, plus harmonic, classical, and candlestick pattern engines. It plots consolidation zones, volume-profile points of control, pattern lines, and forward forecas