ADX 동적 트렌드 전략

저자:차오장, 날짜: 2024-01-15 15:32:45
태그:

img

전반적인 설명

ADX 동적 트렌드 전략 (ADX Dynamic Trend Strategy) 은 ADX 지표를 활용하여 시장 트렌드의 강도와 방향을 결정하는 양적 거래 전략이다. 시장에서 트렌드가 존재하는지 판단하기 위해 평균 방향 지표 (ADX) 를 계산하고 트렌드의 방향을 결정하기 위해 긍정적 방향 지표 (DI+) 및 부정적인 방향 지표 (DI-) 를 계산하여 구매 및 판매 신호를 생성한다.

거래 논리

이 전략은 ADX 지표를 먼저 사용하여 시장에서 추세가 존재하는지 여부를 결정합니다. ADX가 사용자 정의 키 레벨 (23 기본값) 이상일 때 시장 추세가 상대적으로 강하다는 것을 신호합니다. 현재 ADX 값이 n 일 전에 ADX 값보다 높을 때 (n는 사용자 정의 룩백 기간, 기본값 3 일), ADX가 상승하고 시장에서 추세가 형성되고 있음을 신호합니다.

이 전략은 시장 트렌드의 방향을 결정하기 위해 DI+와 DI-를 사용합니다. DI+가 DI-보다 높을 때 시장의 상승 추세를 나타냅니다. DI+가 DI-보다 낮을 때 시장의 하락 추세를 나타냅니다.

마지막으로 전략은 ADX와 DI 분석을 결합하여 특정 구매 및 판매 신호를 생성합니다.

  1. ADX가 상승하고 키 레벨 이상이고 DI+가 DI-보다 높을 때 구매 신호가 생성됩니다.
  2. ADX가 상승하고 키 레벨 이상이고 DI+가 DI-보다 낮을 때 판매 신호가 생성됩니다.
  3. ADX가 감소로 전환되면 평평한 위치 신호가 생성됩니다.

이 전략은 또한 이동 평균 필터링과 사용자 정의 가능한 백테스팅 시간 범위와 같은 기능을 제공합니다.

이점 분석

ADX 동적 트렌드 전략은 다음과 같은 장점을 가지고 있습니다.

  1. 자동으로 시장 트렌드의 존재를 감지하여 비효율적인 거래를 피합니다.
  2. 자동으로 추세에 따라 시장 트렌드의 방향을 결정
  3. 트렌드 존재에 따라 구매하고 트렌드 사라짐에 따라 평평화 하는 명확한 논리
  4. 설정 가능한 이동 평균 필터링은 잘못된 파열을 피합니다.
  5. 과거 테스트를 위한 사용자 정의 가능한 백트테스팅 시간 범위
  6. 다양한 제품에서 최적화를 위한 조정 가능한 지표 매개 변수

위험 분석

이 전략은 또한 몇 가지 위험을 안고 있습니다.

  1. ADX 지표는 늦어지는 효과가 있으며 초기 트렌드 기회를 놓칠 수도 있습니다.
  2. DI에 대한 트렌드 방향 의존은 DI가 민감하기 때문에 잘못된 신호를 생성 할 수 있습니다.
  3. 이동 평균 필터는 단기 기회를 놓칠 수 있습니다.
  4. 부적절한 백테스팅 시간 프레임은 과도한 적합성을 유발할 수 있습니다
  5. 부적절한 지표 매개 변수는 전략 성과에 영향을 줄 수 있습니다.

위험을 줄이기 위해 다음을 고려할 수 있습니다.

  1. ADX 매개 변수를 줄여서 지연을 줄이세요
  2. 잘못된 신호를 방지하기 위해 DI 필터를 제거하거나 조정
  3. 이동 평균 기간을 단축
  4. 전체 표본 테스트를 위해 백테스팅 시간 프레임을 확장
  5. 가장 좋은 설정을 찾기 위해 매개 변수를 최적화

더 나은 기회

이 전략은 다음과 같은 측면에서 향상될 수 있습니다.

  1. 단일 주식 위험을 다양화하기 위해 여러 주식에서 포트폴리오 테스트
  2. 거래 손실에 대한 제어에 스톱 로스 로직을 추가합니다.
  3. 정확도를 높이기 위해 신호 검증을 위한 다른 지표와 결합
  4. 구매/판매 신호를 생성하기 위한 기계 학습 알고리즘을 도입
  5. 동적 조절을 위해 자동 매개 변수 조정 모듈을 추가

결론

ADX 동적 트렌드 전략은 트렌드 존재를 결정하고 트렌드 방향을 결정하기 위해 ADX를 사용합니다. 트렌드가 존재할 때 거래 신호를 생성하고 트렌드가 사라질 때 포지션을 평평하게합니다. 논리는 명확합니다. 트렌드를 자동으로 감지하고 추적함으로써 트렌드가 아닌 시장에서 비효율적인 거래를 어느 정도 피할 수 있습니다. 적절한 향상으로이 전략은 중장기 양적 거래에 강력한 도구가 될 수 있습니다.


/*backtest
start: 2024-01-07 00:00:00
end: 2024-01-14 00:00:00
period: 10m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © millerrh with inspiration from @9e52f12edd034d28bdd5544e7ff92e 
//The intent behind this study is to look at ADX when it has an increasing slope and is above a user-defined key level (23 default). 
//This is to identify when it is trending.
//It then looks at the DMI levels.  If D+ is above D- and the ADX is sloping upwards and above the key level, it triggers a buy condition.  Opposite for short.
//Can use a user-defined moving average to filter long/short if desried.
// NOTE: THIS IS MEANT TO BE USED IN CONJUNCTION WITH MY "ATX TRIGGER" INDICATOR FOR VISUALIZATION. MAKE SURE SETTINGS ARE THE SAME FOR BOTH.

strategy("ADX | DMI Trend", overlay=true, initial_capital=10000, currency='USD', 
   default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.04)

// === BACKTEST RANGE ===
From_Year  = input(defval = 2019, title = "From Year")
From_Month = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
From_Day   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
To_Year    = input(defval = 9999, title = "To Year")
To_Month   = input(defval = 1, title = "To Month", minval = 1, maxval = 12)
To_Day     = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
Start  = timestamp(From_Year, From_Month, From_Day, 00, 00)  // backtest start window
Finish = timestamp(To_Year, To_Month, To_Day, 23, 59)        // backtest finish window

// == INPUTS ==
// ADX Info
adxlen = input(14, title="ADX Smoothing")
dilen = input(14, title="DI Period")
keyLevel = input(23, title="Keylevel for ADX")
adxLookback = input(3, title="Lookback Period for Slope")

// == FILTERING ==
// Inputs
useMaFilter = input(title = "Use MA for Filtering?", type = input.bool, defval = true)
maType = input(defval="EMA", options=["EMA", "SMA"], title = "MA Type For Filtering")
maLength   = input(defval = 200, title = "MA Period for Filtering", minval = 1)

// Declare function to be able to swap out EMA/SMA
ma(maType, src, length) =>
    maType == "EMA" ? ema(src, length) : sma(src, length) //Ternary Operator (if maType equals EMA, then do ema calc, else do sma calc)
maFilter = ma(maType, close, maLength)
plot(maFilter, title = "Trend Filter MA", color = color.green, linewidth = 3, style = plot.style_line, transp = 50)

// Check to see if the useMaFilter check box is checked, this then inputs this conditional "maFilterCheck" variable into the strategy entry 
maFilterCheck = if useMaFilter == true
    maFilter
else
    close

// == USE BUILT-IN DMI FUNCTION TO DETERMINE ADX AND BULL/BEAR STRENGTH
[diplus, diminus, adx] = dmi(dilen, adxlen)

buySignal = (adx[0]-adx[adxLookback] > 0) and adx > keyLevel and diplus > diminus  and close >= maFilterCheck
// buySignalValue = valuewhen(buySignal, close, 0)
shortSignal = (adx[0]-adx[adxLookback] > 0) and adx > keyLevel and diplus < diminus  and close <= maFilterCheck
// shortSignalValue = valuewhen(shortSignal, close, 0)
sellCoverSignal = adx[0]-adx[adxLookback] < 0

// == ENTRY & EXIT CRITERIA
// Triggers to be TRUE for it to fire of the BUY Signal : (opposite for the SELL signal).
// (1): Price is over the 200 EMA line. (EMA level configurable by the user)
// (2): "D+" is OVER the "D-" line
// (3): RSI 7 is under 30 (for SELL, RSI 7 is over 70)
// 1* = The ultimate is to have a combination line of 3 EMA values, EMA 14, EMA 50 and EMA 200 - And if price is over this "combo" line, then it's a strong signal

// == STRATEGY ENTRIES/EXITS == 
strategy.entry("Long", strategy.long, when = buySignal)
strategy.close("Long", when = sellCoverSignal)
strategy.entry("Short", strategy.short, when = shortSignal)
strategy.close("Short", when = sellCoverSignal)
    
// == ALERTS == 
// alertcondition(buySignal, title='ADX Trigger Buy', message='ADX Trigger Buy')
// alertcondition(sellSignal, title='ADX Trigger Sell', message='ADX Trigger Sell')

더 많은