Author: ChaoZhang, Date: 2023-12-04 16:33:45
Tags:

### Overview

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.

### Strategy Logic

1. Calculate the highest high (HH) and lowest low (LL) over a given length. Also calculate ATR over the same length.

2. Calculate +DI and -DI based on upward and downward price moves. Then calculate ADX.

3. 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.

4. If ADX >= 25 and +DI > -DI, market is bullish. If close > upper channel, go long.

5. If ADX >= 25 and +DI < -DI, market is bearish. If close < lower channel, go short.

6. Exit position after exit_length bars since entry.

1. The strategy adapts automatically based on market conditions, using channel strategy in sideways market and trend following in trending market.

### Risk Analysis

1. ADX can generate false signals frequently.

3. Unable to effectively guard against black swan events.

### Optimization Directions

2. Add stop loss to limit losses.

3. Add filters to avoid false signals.

### Conclusion

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

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

dx = math.abs(plusDI - minusDI) / (plusDI + minusDI) * 100

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)

```

More