This strategy is an adaptive price channel strategy based on the Average True Range (ATR) indicator and Average Directional Index (ADX). It aims to identify sideways markets and trends in price movements and make trades accordingly.
Calculate the highest high (HH) and lowest low (LL) over a given length. Also calculate ATR over the same length.
Calculate +DI and -DI based on upward and downward price moves. Then calculate ADX.
If ADX < 25, the market is considered sideways. If close > upper channel (HH - ATR multiplier * ATR), go long. If close < lower channel (LL + ATR multiplier * ATR), go short.
If ADX >= 25 and +DI > -DI, market is bullish. If close > upper channel, go long.
If ADX >= 25 and +DI < -DI, market is bearish. If close < lower channel, go short.
Exit position after exit_length bars since entry.
The strategy adapts automatically based on market conditions, using channel strategy in sideways market and trend following in trending market.
Using ATR and ADX ensures adaptiveness. ATR adjusts channel width, ADX determines trend.
Forced exit adds stability.
ADX can generate false signals frequently.
Poor ATR and ADX parameters lead to bad performance.
Unable to effectively guard against black swan events.
Optimize parameters for ATR and ADX to improve adaptability.
Add stop loss to limit losses.
Add filters to avoid false signals.
The strategy combines indicators and mechanisms to adapt across market conditions. But misjudgements can happen due to indicator limitations. Future optimizations on parameters and risk control.
/*backtest start: 2023-11-03 00:00:00 end: 2023-12-03 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 strategy("Adaptive Price Channel Strategy", overlay=true) length = input(20, title="Length") exit_length = input(10, title="Exit After X Periods") atr_multiplier = input(3.2, title="ATR Multiplier") startDate = input(defval = timestamp("2019-01-15T08:15:15+00:00"), title = "Start Date") endDate = input(defval = timestamp("2033-04-01T08:15:00+00:00"), title = "End Date") hh = ta.highest(high, length) ll = ta.lowest(low, length) atr = ta.atr(length) // calculate +DI and -DI upMove = high - high[1] downMove = low[1] - low plusDM = na(upMove[1]) ? na : (upMove > downMove and upMove > 0 ? upMove : 0) minusDM = na(downMove[1]) ? na : (downMove > upMove and downMove > 0 ? downMove : 0) plusDI = ta.rma(plusDM, length) / atr * 100 minusDI = ta.rma(minusDM, length) / atr * 100 // calculate ADX dx = math.abs(plusDI - minusDI) / (plusDI + minusDI) * 100 adx = ta.rma(dx, length) var int barSinceEntry = na if (not na(close[length]) ) if (adx < 25) // Sideways market if (close > hh - atr_multiplier * atr) strategy.entry("PChLE", strategy.long, comment="PChLE") barSinceEntry := 0 else if (close < ll + atr_multiplier * atr) strategy.entry("PChSE", strategy.short, comment="PChSE") barSinceEntry := 0 else if (adx >= 25 and plusDI > minusDI) // Bullish market if (close > hh - atr_multiplier * atr) strategy.entry("PChLE", strategy.long, comment="PChLE") barSinceEntry := 0 else if (adx >= 25 and plusDI < minusDI) // Bearish market if (close < ll + atr_multiplier * atr) strategy.entry("PChSE", strategy.short, comment="PChSE") barSinceEntry := 0 if (na(barSinceEntry)) barSinceEntry := barSinceEntry[1] + 1 else if (barSinceEntry >= exit_length) strategy.close("PChLE") strategy.close("PChSE") barSinceEntry := na plot(hh, title="Highest High", color=color.green, linewidth=2) plot(ll, title="Lowest Low", color=color.red, linewidth=2)