Momentum Breakout Bi-directional Tracking Strategy

Author: ChaoZhang, Date: 2023-12-18 10:47:46



This strategy combines momentum indicators and bi-directional tracking indicators to capture breakout signals in strong trends for trend tracking. It goes long when prices break out upwards and goes short when prices break downwards. It belongs to the trend tracking strategy category.

Strategy Logic

  1. The HiLo Activator indicator calculates the midpoint price using the midpoint of the highest high and lowest low. When prices break out above the midpoint, a buy signal is generated. When prices break down below the midpoint, a sell signal is generated.

  2. The Average Directional Index (ADX) is used to gauge the strength of the trend. The higher the ADX value, the stronger the trend. This strategy uses ADX with a threshold to filter signals, only generating signals when the trend is strong enough.

  3. The Directional Indicators DI+ and DI- represent the strength of the uptrend and downtrend respectively. This strategy also uses DI+ and DI- thresholds to confirm the strength to avoid wrong signals.

  4. Buy signals are generated when prices break out above the midpoint, ADX is higher than the threshold, and DI+ is higher than the threshold. Sell signals are generated when prices break down below the midpoint, ADX is higher than the threshold, and DI- is higher than the threshold.

Advantage Analysis

This strategy combines the advantages of momentum and trend-following indicators to capture early breakouts and follow trends closely. The strict trend filter conditions also help avoid wrong signals in consolidation and ranging periods.

Compared to using momentum indicators alone, this strategy adds trend strength evaluation to filter signals and improve profitability. Compared to pure trend-following strategies, this strategy can enter trends earlier through breakout signals.

Overall, the strategy can track trends smoothly, enter and exit timely, and avoid being stuck in consolidations while also reducing losses from trend reversals.

Risk Analysis

This strategy has some whipsaw risks from temporary price reversals generating wrong signals. Also, using ADX and DI thresholds may cause missing some early opportunities.

To reduce whipsaw risks, tweak the HiLo Activator parameters to increase the breakout range. To capture more opportunities, lower the ADX and DI thresholds at the expense of signal quality.

Users should also note differences across products and market environments. Higher thresholds generally work better for commodities while lower thresholds suit stocks and forex.

Optimization Directions

The main ways to optimize this strategy include:

  1. Adjust the HiLo Activator period and trigger levels to balance whipsaw risks and timing.

  2. Tweak ADX period and threshold to balance signal quality and frequency.

  3. Set separate thresholds for DI+ and DI- to accommodate differences between uptrends and downtrends.

  4. Add stop loss strategies with stop loss levels to control single trade loss.

  5. Combine with other auxiliary indicators to improve overall stability.


This strategy considers both momentum and trend-following indicators to generate signals during strong trends. It has the advantage of following trends smoothly and closely, suitable for capturing early trend opportunities. It also has reasonable risk control abilities to reduce losses from wrong signals and whipsaws. With parameter tuning and stop loss additions, it can achieve steady performance. As a versatile trend tracking strategy fitting different products and markets, it deserves good attention and application from quant traders.

start: 2022-12-11 00:00:00
end: 2023-12-17 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]

strategy("HiLo Activator with ADX", shorttitle="HASB_ADX", overlay=true)

// Parameters for the HiLo Activator
length_ha = input(14, title="HiLo Activator Period")
offset_ha = input(0, title="Offset")
trigger_ha = input(1, title="Trigger for Buy/Sell")

// Parameters for ADX
adx_length = input(14, title="ADX Period", minval=1)
adx_threshold = input(25, title="ADX Threshold")
di_threshold = input(50, title="DI Threshold")

// Parameter for choosing the number of candles for backtest
backtest_candles = input(1000, title="Number of Candles for Backtest", minval=1)

// Function to get backtest data
getBacktestData() =>
    var float data = na
    if bar_index >= backtest_candles
        data := security(syminfo.tickerid, "D", close[backtest_candles])

// HiLo Activator calculations
ha = (highest(high, length_ha) + lowest(low, length_ha)) / 2

// ADX calculations
trh = high - high[1]
trl = low[1] - low
tr = max(trh, trl)
atr = sma(tr, adx_length)
plus_dm = high - high[1] > low[1] - low ? max(high - high[1], 0) : 0
minus_dm = low[1] - low > high - high[1] ? max(low[1] - low, 0) : 0
smoothed_plus_dm = sma(plus_dm, adx_length)
smoothed_minus_dm = sma(minus_dm, adx_length)
di_plus = 100 * (smoothed_plus_dm / atr)
di_minus = 100 * (smoothed_minus_dm / atr)
dx = 100 * abs(di_plus - di_minus) / (di_plus + di_minus)
adx = sma(dx, adx_length)

// Buy and Sell signals based on HiLo Activator and ADX
signalLong = crossover(close, ha) and adx > adx_threshold and di_plus > di_threshold
signalShort = crossunder(close, ha) and adx > adx_threshold and di_minus > di_threshold

// Plot HiLo Activator and ADX
plot(ha,, title="HiLo Activator")
plot(offset_ha,, style=plot.style_histogram, title="Offset")
plot(adx, color=color.purple, title="ADX")

// Backtest strategy
strategy.entry("Buy", strategy.long, when = signalLong)
strategy.entry("Sell", strategy.short, when = signalShort)
strategy.close("Buy", when = signalShort)
strategy.close("Sell", when = signalLong)

// Accuracy percentage
var accuracy = 0.0
var totalTrades = 0
var winningTrades = 0

if (signalLong or signalShort)
    totalTrades := totalTrades + 1

if (signalLong and (not na(signalLong[1]) and (not signalLong[1])))
    winningTrades := winningTrades + 1

if (signalShort and (not na(signalShort[1]) and (not signalShort[1])))
    winningTrades := winningTrades + 1

accuracy := totalTrades > 0 ? (winningTrades / totalTrades) * 100 : 0

// Plot accuracy percentage on the chart
plot(accuracy, title="Accuracy Percentage", color=color.purple, style=plot.style_histogram)