The momentum breakout strategy
The momentum breakout strategy is a trend-following strategy that tracks the momentum of the market. It combines multiple indicators to judge whether the market is currently in an upward or downward trend, and opens…

Overview
The momentum breakout strategy is a trend-following strategy that tracks the momentum of the market. It combines multiple indicators to judge whether the market is currently in an upward or downward trend, and opens long positions when breaking through key resistance levels and opens short positions when breaking through key support levels.
Strategy Logic
This strategy mainly uses Donchian Channels of multiple timeframes to determine market trends and key price levels. Specifically, when prices break through the upper rail of the longer-term Donchian Channel such as 40 days, it is judged as an uptrend. Together with additional filters like new highs within the year and the alignment of moving averages, long signals are triggered. When prices break below the lower rail of the longer-term Donchian Channel, it is judged as a downtrend. Together with filters like new lows within the year, short signals are triggered.
The strategy provides two options for exit positions: fixed invalidation line and trailing stop loss. The fixed invalidation line uses the lower/upper rail of a shorter Donchian Channel such as 20 days. The trailing stop loss calculates a dynamic stop loss line each day based on ATR values. Both methods can control risks effectively.
Advantage Analysis
This strategy combines trend judgment and breakout operations, which can effectively capture short-term directional opportunities in the market. Compared with single indicators, it uses multiple filters that can filter out some false breakouts and improve the quality of entry signals. In addition, the application of stop loss strategies also enhances its resilience and can effectively control losses even if the market pulls back briefly.
Risk Analysis
The main risk of this strategy is that prices may fluctuate violently, triggering stop losses to exit positions. If prices reverse rapidly afterwards, opportunities could be missed. In addition, the use of multiple filters may also filter out some opportunities and reduce the frequency of trades.
To reduce risks, ATR multiples can be adjusted or Donchian Channel intervals can be widened to decrease the likelihood of stop loss being hit. Some filters could also be removed or relaxed to increase entry frequency, but risks would also increase.
Optimization Directions
This strategy can be optimized in the following aspects:
- Optimize the lengths of the Donchian Channels to find the best combination of parameters.
- Try different types of moving averages as filters.
- Adjust the ATR multiplier or use fixed points for stop loss.
- Add more trend judging indicators like MACD.
- Optimize the lookback periods for new highs/lows within the year etc.
By testing different parameters, the optimum combination balancing risks and returns can be found.
Conclusion
This strategy combines multiple indicators to determine trend direction and triggers trades at key breakout levels. Its stop loss mechanism also makes it resilient to risks. By optimizing parameters, stable excess returns can be achieved. It suits investors who have no clear view on the market but wish to follow trends.
Parameters
| Name | Default | What it controls |
|---|---|---|
| v_input_1 | 40 | donchianEntryLength |
| v_input_2 | 20 | donchianExitLength |
| v_input_3 | true | considerNewLongTermHighLows |
| v_input_4 | 120 | shortHighLowPeriod |
| v_input_5 | 180 | longHighLowPeriod |
| v_input_6 | true | considerMAAlignment |
| v_input_7 | 0 | Moving Average Type: ema | sma | hma | rma | vwma | wma |
| v_input_8 | 40 | LookbackPeriod |
| v_input_9 | 22 | atrLength |
| v_input_10 | 4 | atrMult |
| v_input_11 | 0 | Exit Strategy: tsl | dc |
| v_input_12 | true | considerYearlyHighLow |
| v_input_13 | 10 | backtestYears |
Source Pine Script
/*backtest
start: 2024-01-23 00:00:00
end: 2024-02-22 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © HeWhoMustNotBeNamed
//@version=4
strategy("BuyHigh-SellLow Strategy", overlay=true, initial_capital = 10000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, pyramiding = 1, commission_value = 0.01, calc_on_order_fills = true)
donchianEntryLength = input(40, step=10)
donchianExitLength = input(20, step=10)
considerNewLongTermHighLows = input(true)
shortHighLowPeriod = input(120, step=10)
longHighLowPeriod = input(180, step=10)
considerMAAlignment = input(true)
MAType = input(title="Moving Average Type", defval="ema", options=["ema", "sma", "hma", "rma", "vwma", "wma"])
LookbackPeriod = input(40, minval=10,step=10)
atrLength = input(22)
atrMult = input(4)
exitStrategy = input(title="Exit Strategy", defval="tsl", options=["dc", "tsl"])
considerYearlyHighLow = input(true)
backtestYears = input(10, minval=1, step=1)
f_getMovingAverage(source, MAType, length)=>
ma = sma(source, length)
if(MAType == "ema")
ma := ema(source,length)
if(MAType == "hma")
ma := hma(source,length)
if(MAType == "rma")
ma := rma(source,length)
if(MAType == "vwma")
ma := vwma(source,length)
if(MAType == "wma")
ma := wma(source,length)
ma
f_getTrailingStop(atr, atrMult)=>
stop = close - atrMult*atr
stop := strategy.position_size > 0 ? max(stop, stop[1]) : stop
stop
f_getMaAlignment(MAType, includePartiallyAligned)=>
ma5 = f_getMovingAverage(close,MAType,5)
ma10 = f_getMovingAverage(close,MAType,10)
ma20 = f_getMovingAverage(close,MAType,20)
ma30 = f_getMovingAverage(close,MAType,30)
ma50 = f_getMovingAverage(close,MAType,50)
ma100 = f_getMovingAverage(close,MAType,100)
ma200 = f_getMovingAverage(close,MAType,200)
upwardScore = 0
upwardScore := close > ma5? upwardScore+1:upwardScore
upwardScore := ma5 > ma10? upwardScore+1:upwardScore
upwardScore := ma10 > ma20? upwardScore+1:upwardScore
upwardScore := ma20 > ma30? upwardScore+1:upwardScore
upwardScore := ma30 > ma50? upwardScore+1:upwardScore
upwardScore := ma50 > ma100? upwardScore+1:upwardScore
upwardScore := ma100 > ma200? upwardScore+1:upwardScore
upwards = close > ma5 and ma5 > ma10 and ma10 > ma20 and ma20 > ma30 and ma30 > ma50 and ma50 > ma100 and ma100 > ma200
downwards = close < ma5 and ma5 < ma10 and ma10 < ma20 and ma20 < ma30 and ma30 < ma50 and ma50 < ma100 and ma100 < ma200
upwards?1:downwards?-1:includePartiallyAligned ? (upwardScore > 5? 0.5: upwardScore < 2?-0.5:upwardScore>3?0.25:-0.25) : 0
//////////////////////////////////// Calculate new high low condition //////////////////////////////////////////////////
f_calculateNewHighLows(shortHighLowPeriod, longHighLowPeriod, considerNewLongTermHighLows)=>
newHigh = highest(shortHighLowPeriod) == highest(longHighLowPeriod) or not considerNewLongTermHighLows
newLow = lowest(shortHighLowPeriod) == lowest(longHighLowPeriod) or not considerNewLongTermHighLows
[newHigh,newLow]
//////////////////////////////////// Calculate Yearly High Low //////////////////////////////////////////////////
f_getYearlyHighLowCondition(considerYearlyHighLow)=>
yhigh = security(syminfo.tickerid, '12M', high[1])
ylow = security(syminfo.tickerid, '12M', low[1])
yhighlast = yhigh[365]
ylowlast = ylow[365]
yhighllast = yhigh[2 * 365]
ylowllast = ylow[2 * 365]
yearlyTrendUp = na(yhigh)? true : na(yhighlast)? close > yhigh : na(yhighllast)? close > max(yhigh,yhighlast) : close > max(yhigh, min(yhighlast, yhighllast))
yearlyHighCondition = ( (na(yhigh) or na(yhighlast) ? true : (yhigh > yhighlast) ) and ( na(yhigh) or na(yhighllast) ? true : (yhigh > yhighllast))) or yearlyTrendUp or not considerYearlyHighLow
yearlyTrendDown = na(ylow)? true : na(ylowlast)? close < ylow : na(ylowllast)? close < min(ylow,ylowlast) : close < min(ylow, max(ylowlast, ylowllast))
yearlyLowCondition = ( (na(ylow) or na(ylowlast) ? true : (ylow < ylowlast) ) and ( na(ylow) or na(ylowllast) ? true : (ylow < ylowllast))) or yearlyTrendDown or not considerYearlyHighLow
label_x = time+(60*60*24*1000*1)
[yearlyHighCondition,yearlyLowCondition]
donchian(rangeLength)=>
upper = highest(rangeLength)
lower = lowest(rangeLength)
middle = (upper+lower)/2
[middle, upper, lower]
inDateRange = true
[eMiddle, eUpper, eLower] = donchian(donchianEntryLength)
[exMiddle, exUpper, exLower] = donchian(donchianExitLength)
maAlignment = f_getMaAlignment(MAType, false)
[yearlyHighCondition, yearlyLowCondition] = f_getYearlyHighLowCondition(considerYearlyHighLow)
[newHigh,newLow] = f_calculateNewHighLows(shortHighLowPeriod, longHighLowPeriod, considerNewLongTermHighLows)
maAlignmentLongCondition = highest(maAlignment, LookbackPeriod) == 1 or not considerMAAlignment
atr = atr(atrLength)
tsl = f_getTrailingStop(atr, atrMult)
//U = plot(eUpper, title="Up", color=color.green, linewidth=2, style=plot.style_linebr)
//D = plot(exLower, title="Ex Low", color=color.red, linewidth=2, style=plot.style_linebr)
longCondition = crossover(close, eUpper[1]) and yearlyHighCondition and newHigh and maAlignmentLongCondition
exitLongCondition = crossunder(close, exLower[1])
shortCondition = crossunder(close, eLower[1]) and yearlyLowCondition and newLow
exitShortCondition = crossover(close, exUpper[1])
strategy.entry("Buy", strategy.long, when=longCondition and inDateRange, oca_name="oca_buy")
strategy.exit("ExitBuyDC", "Buy", when=exitStrategy=='dc', stop=exLower)
strategy.exit("ExitBuyTSL", "Buy", when=exitStrategy=='tsl', stop=tsl)
plot(strategy.position_size > 0 ? (exitStrategy=='dc'?exLower:tsl) : na, title="Trailing Stop", color=color.red, linewidth=2, style=plot.style_linebr)
//strategy.close("Buy", when=exitLongCondition)Published by ChaoZhang on the FMZ strategy square · last modified 2024-02-23. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.
Build this with AgenKit
A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/The-momentum-breakout-strategy.md- npx agenkit install engineering-kit in your project
- Paste the command into your agent and approve each phase
- Get tests, backtest, risk controls and a paper-trading switch
Understand it first
Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.
Related specs
- Donchian Channel and Larry Williams Large Trade Index StrategyPine Script · Breakout · 1m
- Momentum Breakout Trading Strategy 435896Pine Script · Breakout · 1d
- Multi Indicator Trend Breakout Strategy with Dynamic Stop LossPine Script · Breakout · 1d
- Trend Following Strategy with MACD and Donchian ChannelPine Script · Breakout · 1h
- Integrated Ichimoku Keltner Trading System Based on Moving Average StrategyPine Script · Breakout · 1h
- Dynamic Oscillation Breakout StrategyPine Script · Breakout · 1d