이중 이동 평균 반전 전략 (Dual Moving Average Reversion Strategy) 은 전형적인 단기 평균 반전 거래 전략이다. 이 전략은 다른 매개 변수 설정을 가진 두 개의 이동 평균에 의해 거래 신호를 생성한다. 트렌드 반전이 발생할 때 이익을 얻는 것을 목표로 한다.
이 전략은 두 개의 이동 평균을 사용하여 거래 신호를 생성합니다. 첫 번째 MA 마오프닝은 트렌드 방향을 결정하는 데 사용됩니다. 두 번째 MA 매클로싱은 거래 신호를 생성하는 데 사용됩니다.
마오프닝이 상승하면 현재 시장이 상승 추세에 있음을 나타냅니다. 마오프닝이 하락하면 현재 시장이 하락 추세에 있음을 나타냅니다. 매클로싱은 초기 반전 신호를 생성하는 데 더 민감하게 만들기 위해 1보다 큰 계수로 곱됩니다.
구체적으로, 마오페닝이 상승하고 마오페닝이 마오페닝 아래로 넘어가면 트렌드 역전을 나타냅니다. 전략은 짧은 포지션을 열 것입니다. 마오페닝이 하락하고 마오페닝이 마오페닝 위에 넘어가면 트렌드 역전을 나타냅니다. 전략은 긴 포지션을 열 것입니다.
전략의 매개 변수에는 MA 유형, 길이, 데이터 소스 등이 포함됩니다. 이러한 매개 변수를 조정하여 거래 성능을 최적화 할 수 있습니다. 또한 엔트리 규칙, 스톱 로스 등과 같은 구성 가능한 옵션이 있습니다.
이중 MA 반전 전략의 주요 장점은 다음과 같습니다.
짧은 기간 거래에 적합한 작은 드라우다운. 빠른 이동 평균은 짧은 기간의 반전을 더 작은 드라우다운으로 빠르게 포착 할 수 있습니다.
구현이 간단하고 이해하기 쉽습니다. 두 MA의 크로스오버는 명확한 거래 신호를 생성합니다.
여러 개의 조절 가능한 매개 변수와 함께 매우 구성 가능. 두 개의 MA와 계수의 매개 변수를 최적화 할 수 있습니다.
명확한 논리 흐름으로 자동화하기 쉽습니다. 간단한 논리와 높은 주파수 거래는 자동화 거래에 매우 적합합니다.
스톱 로스 메커니즘으로 제어 가능한 위험. 이동 스톱 로스 또는 가치 스톱 로스는 단일 거래의 손실을 제한할 수 있습니다.
이 전략에는 몇 가지 위험도 있습니다.
MA 크로스오버 신호의 지연. MA 자체는 가격에 지연합니다. 크로스오버는 추세가 잠시 뒤집어진 후에 발생할 수 있습니다.
윙사 트레이드 위험. 역전 추세는 빠르게 다시 역전되어 연속 손실을 초래할 수 있습니다.
마감률은 여전히 존재합니다. 단 하나의 손실을 제한하지만 연속적인 마감률은 여전히 큰 마감률으로 이어질 수 있습니다.
과도한 매개 변수 최적화는 실시간 거래에서 과도한 적합성과 저성능으로 이어질 수 있습니다.
그 해결책은 다음과 같습니다.
더 빠른 MAs를 찾기 위해 매개 변수를 최적화해
부피와 변동성 지표와 같은 필터를 추가하여 윙사 트레이드를 피합니다.
연속적인 스톱 로스의 확률을 낮추기 위해 스톱 로스 위치를 조정합니다.
과도한 장착 위험을 평가하기 위한 매개 변수 집합의 견고성 테스트
이 전략은 다음 측면에서 더 이상 최적화 될 수 있습니다.
다른 종류의 MAs를 테스트하여 KAMA, ZLEMA 등과 같이 더 민감한 MAs를 찾으십시오.
최적의 조합을 찾기 위해 MA 길이를 최적화하십시오. 일반적으로 짧은 기간은 더 나은 성능을 가지고 있습니다.
다른 데이터 소스를 테스트합니다. 밀접한 가격, 중간 가격, 전형적인 가격 등.
트렌드 필터를 추가해서 도
MACD, OBV 등과 같은 확인을 위한 다른 지표를 추가합니다.
위험 관리 메커니즘을 강화합니다. 예를 들어 스톱 로스, 최대 계좌 손실 등을 이동하는 것.
최적의 자산 배분을 찾기 위해 포트폴리오 최적화
부착 위험을 평가하기 위한 매개 변수의 견고성 테스트
이중 MA 반전은 간단하고 실용적인 단기 거래 전략이다. 양적 거래로 단기 반전을 포착하는 데 적합하다. 그러나 지연 및 윙사 트레이드와 같은 위험이 존재한다. 이 전략은 매개 변수를 최적화하고 필터를 추가하고 위험 통제 등을 강화하여 안정적이고 효율적인 전략을 개발하여 좋은 실제 거래 성과를 낼 수 있다.
/*backtest start: 2023-10-17 00:00:00 end: 2023-11-16 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 strategy(title = "hamster-bot MRS 2", overlay = true, default_qty_type = strategy.percent_of_equity, initial_capital = 100, default_qty_value = 100, pyramiding = 9, commission_value = 0.045, backtest_fill_limits_assumption = 1) info_options = "Options" on_close = input(false, title = "Entry on close", inline=info_options, group=info_options) OFFS = input.int(0, minval = 0, maxval = 1, title = "| Offset View", inline=info_options, group=info_options) trade_offset = input.int(0, minval = 0, maxval = 1, title = "Trade", inline=info_options, group=info_options) use_kalman_filter = input.bool(false, title="Use Kalman filter", group=info_options) //MA Opening info_opening = "MA Opening" maopeningtyp = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_opening, group=info_opening) maopeningsrc = input.source(ohlc4, title = "", inline=info_opening, group=info_opening) maopeninglen = input.int(3, minval = 1, maxval = 200, title = "", inline=info_opening, group=info_opening) //MA Closing info_closing = "MA Closing" maclosingtyp = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_closing, group=info_closing) maclosingsrc = input.source(ohlc4, title = "", inline=info_closing, group=info_closing) maclosinglen = input.int(3, minval = 1, maxval = 200, title = "", inline=info_closing, group=info_closing) maclosingmul = input.float(1, step = 0.005, title = "mul", inline=info_closing, group=info_closing) long1on = input(true, title = "", inline = "long1") long1shift = input.float(0.96, step = 0.005, title = "Long", inline = "long1") long1lot = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "long1") short1on = input(true, title = "", inline = "short1") short1shift = input.float(1.04, step = 0.005, title = "short", inline = "short1") short1lot = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "short1") startTime = input(timestamp("01 Jan 2010 00:00 +0000"), "Start date", inline = "period") finalTime = input(timestamp("31 Dec 2030 23:59 +0000"), "Final date", inline = "period") HMA(_src, _length) => ta.wma(2 * ta.wma(_src, _length / 2) - ta.wma(_src, _length), math.round(math.sqrt(_length))) EHMA(_src, _length) => ta.ema(2 * ta.ema(_src, _length / 2) - ta.ema(_src, _length), math.round(math.sqrt(_length))) THMA(_src, _length) => ta.wma(ta.wma(_src,_length / 3) * 3 - ta.wma(_src, _length / 2) - ta.wma(_src, _length), _length) tema(sec, length)=> tema1= ta.ema(sec, length) tema2= ta.ema(tema1, length) tema3= ta.ema(tema2, length) tema_r = 3*tema1-3*tema2+tema3 donchian(len) => math.avg(ta.lowest(len), ta.highest(len)) ATR_func(_src, _len)=> atrLow = low - ta.atr(_len) trailAtrLow = atrLow trailAtrLow := na(trailAtrLow[1]) ? trailAtrLow : atrLow >= trailAtrLow[1] ? atrLow : trailAtrLow[1] supportHit = _src <= trailAtrLow trailAtrLow := supportHit ? atrLow : trailAtrLow trailAtrLow f_dema(src, len)=> EMA1 = ta.ema(src, len) EMA2 = ta.ema(EMA1, len) DEMA = (2*EMA1)-EMA2 f_zlema(src, period) => lag = math.round((period - 1) / 2) ema_data = src + (src - src[lag]) zl= ta.ema(ema_data, period) f_kalman_filter(src) => float value1= na float value2 = na value1 := 0.2 * (src - src[1]) + 0.8 * nz(value1[1]) value2 := 0.1 * (ta.tr) + 0.8 * nz(value2[1]) lambda = math.abs(value1 / value2) alpha = (-math.pow(lambda, 2) + math.sqrt(math.pow(lambda, 4) + 16 * math.pow(lambda, 2)))/8 value3 = float(na) value3 := alpha * src + (1 - alpha) * nz(value3[1]) //SWITCH ma_func(modeSwitch, src, len, use_k_f=true) => modeSwitch == "SMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.sma(src, len)) : ta.sma(src, len) : modeSwitch == "RMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.rma(src, len)) : ta.rma(src, len) : modeSwitch == "EMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.ema(src, len)) : ta.ema(src, len) : modeSwitch == "TEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(tema(src, len)) : tema(src, len): modeSwitch == "DEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(f_dema(src, len)) : f_dema(src, len): modeSwitch == "ZLEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(f_zlema(src, len)) : f_zlema(src, len): modeSwitch == "WMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.wma(src, len)) : ta.wma(src, len): modeSwitch == "VWMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.vwma(src, len)) : ta.vwma(src, len): modeSwitch == "Hma" ? use_kalman_filter and use_k_f ? f_kalman_filter(HMA(src, len)) : HMA(src, len): modeSwitch == "Ehma" ? use_kalman_filter and use_k_f ? f_kalman_filter(EHMA(src, len)) : EHMA(src, len): modeSwitch == "Thma" ? use_kalman_filter and use_k_f ? f_kalman_filter(THMA(src, len/2)) : THMA(src, len/2): modeSwitch == "ATR" ? use_kalman_filter and use_k_f ? f_kalman_filter(ATR_func(src, len)): ATR_func(src, len) : modeSwitch == "L" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.lowest(len)): ta.lowest(len) : modeSwitch == "H" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.highest(len)): ta.highest(len) : modeSwitch == "DMA" ? donchian(len) : na //Var sum = 0.0 maopening = 0.0 maclosing = 0.0 os = maopeningsrc cs = maclosingsrc pos = strategy.position_size p = 0.0 p := pos == 0 ? (strategy.equity / 100) / close : p[1] truetime = true loss = 0.0 maxloss = 0.0 equity = 0.0 //MA Opening maopening := ma_func(maopeningtyp, maopeningsrc, maopeninglen) //MA Closing maclosing := ma_func(maclosingtyp, maclosingsrc, maclosinglen) * maclosingmul long1 = long1on == false ? 0 : long1shift == 0 ? 0 : long1lot == 0 ? 0 : maopening == 0 ? 0 : maopening * long1shift short1 = short1on == false ? 0 : short1shift == 0 ? 0 : short1lot == 0 ? 0 : maopening == 0 ? 0 : maopening * short1shift //Colors maopeningcol = maopening == 0 ? na : color.blue maclosingcol = maclosing == 0 ? na : color.fuchsia long1col = long1 == 0 ? na : color.green short1col = short1 == 0 ? na : color.red //Lines plot(maopening, offset = OFFS, color = maopeningcol) plot(maclosing, offset = OFFS, color = maclosingcol) long1line = long1 == 0 ? close : long1 short1line = short1 == 0 ? close : short1 plot(long1line, offset = OFFS, color = long1col) plot(short1line, offset = OFFS, color = short1col) //Lots lotlong1 = p * long1lot lotshort1 = p * short1lot //Entry if maopening > 0 and maclosing > 0 and truetime //Long sum := 0 strategy.entry("L", strategy.long, lotlong1, limit = on_close ? na : long1, when = long1 > 0 and pos <= sum and (on_close ? close <= long1[trade_offset] : true)) sum := lotlong1 //Short sum := 0 pos := -1 * pos strategy.entry("S", strategy.short, lotshort1, limit = on_close ? na : short1, when = short1 > 0 and pos <= sum and (on_close ? close >= short1[trade_offset] : true)) sum := lotshort1 strategy.exit("Exit", na, limit = maclosing) if time > finalTime strategy.close_all()