양적 이동 평균을 기반으로 한 추세 추적 전략


생성 날짜: 2023-09-18 13:23:52 마지막으로 수정됨: 2023-09-18 13:23:52
복사: 0 클릭수: 637
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

개요

이 전략은 거래량에 기반한 두 개의 이동 평균을 계산하고 그 차이의 방향에 따라 현재의 트렌드 방향을 판단하여 긴 포지션 또는 짧은 포지션 작업을 수행합니다. 이 전략은 간단하고 쉽게 실행할 수 있으며 시장의 흐름을 효과적으로 추적 할 수 있습니다.

전략 원칙

  1. 빠른 선과 느린 선을 계산한다. 빠른 선은 사용자 정의 된 빠른 선 주기, 느린 선은 느린 선 주기 기반의 양적 이동 평균이다.

  2. 두 선의 차이를 계산한다. 빠른 선 빼기 느린 선은 차차값 곡선을 얻는다.

  3. 트렌드 방향을 판단한다. 빠른 선에서 느린 선을 통과할 때 상향 신호로, 더 많이 한다. 빠른 선 아래에서 느린 선을 통과할 때 하향 신호로, 공백한다.

  4. 거래 신호를 발신한다. 부진할 때 다수 신호를 발신한다. 하락할 때 공백 신호를 발신한다.

  5. 스톱을 설정한다. 사용자 정의의 고정 스톱 퍼센트 또는 ATR 기반의 동적 스톱을 통해 스톱 위치를 설정한다.

  6. 출장 조건 △ 지분을 보유할 때 스톱 손실이나 역전 신호가 발생하면 평점 지분을 출장한다 △

우위 분석

  1. 양적 지표를 사용하여 트렌드를 식별하여 가짜 돌파구에 의해 오해되지 않습니다.

  2. 빠른 속도와 느린 속도 라인은 시장 소음을 필터링하여 거래 빈도를 줄일 수 있습니다.

  3. 손해 방지 설정은 손실 위험을 효과적으로 제어한다.

  4. 전략의 논리는 간단하고 명확하며, 구현을 이해하기 쉽습니다.

  5. 다양한 품종과 시간적 기간의 필요에 맞게 사용자 정의 가능한 파라미터.

위험 분석

  1. 잘못된 매개 변수 설정으로 인해 거래 빈도가 너무 높거나 트렌드를 놓칠 수 있습니다.

  2. 고정 스톱은 시장의 변화에 적응하기에는 너무 기계적일 수 있습니다.

  3. 양과 가격의 관계가 변화하면 양적 지표의 효과에 영향을 줄 수 있다.

  • 위험 1은 최적화 매개 변수를 통해 최적의 조합을 찾을 수 있다.

  • 리스크 2는 동적 ATR 상쇄를 사용하여 고정 상쇄를 대체할 수 있습니다.

  • 위험 3은 거래량 변화에 대한 전략의 영향을 고려해야 합니다.

최적화 방향

  1. 다양한 패스트라인과 슬로우라인 파라미터 조합을 테스트한다.

  2. OBV, 윌리엄스 등과 같은 다른 수량형 지표를 시도해보세요.

  3. 변동율에 기반한 손실을 증가시켜야 한다.

  4. 다른 지표와 함께 사용된 효과를 평가한다.

  5. 다양한 거래 품종에 대한 효과를 평가한다.

요약하다

이 전략은 양적 평균의 빠른 느린 선의 조합을 통해 트렌드를 추적하고 거래 논리는 간단하고 명확하며, 파라미터를 최적화 조정할 수 있습니다. 스톱 손실 설정은 위험을 제어하는 데 도움이됩니다. 후속으로 다른 지표 조합과 사용 된 효과를 계속 평가 할 수 있습니다.

전략 소스 코드
/*backtest
start: 2023-08-18 00:00:00
end: 2023-09-17 00:00:00
period: 2h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("EVWMA 6HR", overlay=false, precision=2, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.075)
// Credit to QuantNomad for the main idea behind this code
/////////////// Time Frame ///////////////
_1 = input(false,  "════════ Test Period ═══════")
testStartYear = input(2017, "Backtest Start Year") 
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay, 0, 0)

testStopYear = input(2019, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay, 0, 0)

testPeriod() => true

///////////// EVWMA /////////////
_2 = input(false,  "════════ EVMA ═══════")

fast_sum_length = input(5, title = "Fast Sum Length",  type = input.integer)
slow_sum_length = input(11, title = "Slow Sum Length",  type = input.integer)

fast_vol_period = sum(volume, fast_sum_length)
slow_vol_period = sum(volume, slow_sum_length)

fast_evwma = 0.0
fast_evwma := ((fast_vol_period - volume) * nz(fast_evwma[1], close) + volume * close) / (fast_vol_period)
slow_evwma = 0.0
slow_evwma := ((slow_vol_period - volume) * nz(slow_evwma[1], close) + volume * close) / (slow_vol_period)

diff = fast_evwma - slow_evwma

///////////////  Strategy  /////////////// 
long = fast_evwma > slow_evwma 
short = fast_evwma < slow_evwma 

last_long = 0.0
last_short = 0.0
last_long := long ? time : nz(last_long[1])
last_short := short ? time : nz(last_short[1])

long_signal = crossover(last_long, last_short)
short_signal = crossover(last_short, last_long)

last_open_long_signal = 0.0
last_open_short_signal = 0.0
last_open_long_signal := long_signal ? open : nz(last_open_long_signal[1])
last_open_short_signal := short_signal ? open : nz(last_open_short_signal[1])

last_long_signal = 0.0
last_short_signal = 0.0
last_long_signal := long_signal ? time : nz(last_long_signal[1])
last_short_signal := short_signal ? time : nz(last_short_signal[1])

in_long_signal = last_long_signal > last_short_signal
in_short_signal = last_short_signal > last_long_signal

last_high = 0.0
last_low = 0.0
last_high := not in_long_signal ? na : in_long_signal and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_short_signal ? na : in_short_signal and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])

since_longEntry = barssince(last_open_long_signal != last_open_long_signal[1]) 
since_shortEntry = barssince(last_open_short_signal != last_open_short_signal[1]) 

/////////////// Dynamic ATR Stop Losses ///////////////
_4 = input(false,  "════════ Stop Loss ═══════")
SL_type = input("Fixed", options=["Fixed", "ATR Derived"], title="Stop Loss Type")
sl_inp = input(9.0, title='Fixed Stop Loss %') / 100
atrLkb = input(20, minval=1, title='ATR Stop Period')
atrMult = input(1.5, step=0.25, title='ATR Stop Multiplier') 
atr1 = atr(atrLkb)

longStop1 = 0.0
longStop1 :=  short_signal ? na : long_signal ? close - (atr1 * atrMult) : longStop1[1]
shortStop1 = 0.0
shortStop1 := long_signal ? na : short_signal ? close + (atr1 * atrMult) : shortStop1[1]

slLong = in_long_signal ? strategy.position_avg_price * (1 - sl_inp) : na
slShort = strategy.position_avg_price * (1 + sl_inp)
long_sl = in_long_signal ? slLong : na
short_sl = in_short_signal ? slShort : na

_5 = input(false,  "══════ Longs or Shorts ═════")
useLongs = input(true, title="Use Longs")
useShorts = input(true, title="Use Shorts")

/////////////// Execution ///////////////
if testPeriod()
    if useLongs
        strategy.entry("L", strategy.long, when=long)
        strategy.exit("L SL", "L", stop = SL_type == "Fixed" ? long_sl : longStop1, when=since_longEntry > -1)
    if useShorts
        strategy.exit("S SL", "S", stop = SL_type == "Fixed" ? short_sl : shortStop1, when=since_shortEntry > -1)
        strategy.entry("S", strategy.short, when=short)
    if not useShorts
        strategy.close("L", when=short)
    if not useLongs
        strategy.close("S", when=long)

/////////////// Plotting /////////////// 
bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=30)
p1 = plot(diff, title = "Delta", color = long ? color.lime : short ? color.red : na, transp=0)
p2 = plot(0, color = color.white)
fill(p1, p2, color = long ? color.lime : short ? color.red : na, transp=60)