
이중 이동 평균 역전 전략 (Dual Moving Average Reversion Strategy) 은 전형적인 단기 역전 거래 전략이다. 이 전략은 두 개의 다른 파라미터 세트의 이동 평균을 사용하여 거래 신호를 발산하고, 추세가 역전될 때 이익을 취한다.
이 전략은 두 개의 평선으로 거래 신호를 생성한다. 첫 번째 평선 maopening는 트렌드 방향을 판단하기 위해, 두 번째 평선 maclosing은 거래 신호를 발산하기 위해 사용된다.
마오오펜닝이 올라갈 때, 현재 트렌드 상승 단계에 있다는 것을 나타냅니다. 마오펜닝이 떨어질 때, 현재 트렌드 하락 단계에 있다는 것을 나타냅니다. 맥로싱은 1보다 큰 계수로 곱하여 더 민감하게 반응하여 반전 신호를 더 일찍 발송 할 수 있습니다.
구체적으로 말해서, maopening이 상승하고 maclosing이 아래로 maopening을 뚫었을 때, 트렌드 반전이 나타납니다. 이 때 전략은 공백을 열게 됩니다. maopening이 떨어지고 maclosing이 maopening을 뚫었을 때, 트렌드 반전이 나타납니다. 이 때 전략은 더 많은 위치를 열게 됩니다.
이 전략의 매개 변수는 평균선 유형, 길이, 데이터 소스 등으로, 이러한 매개 변수를 조정하여 더 나은 거래 효과를 얻을 수 있습니다. 또한, 전략은 포지션 개시 방법, 손실 방법 등과 같은 몇 가지 옵션이 내장되어 있으며, 필요에 따라 설정할 수 있습니다.
이중 평행선 역전 전략의 장점은 주로 다음과 같습니다.
작은 회귀, 짧은 라인 거래에 적합하다. 두 개의 빠른 평균 라인을 사용하여 단기 트렌드의 반전을 빠르게 잡을 수 있으며, 작은 회귀가 있다.
간단하고 쉽게 이해할 수 있습니다. 쌍평선으로 이루어진 교차는 거래 신호입니다. 매우 간단하고 명확합니다.
조정 가능한 파라미터가 많고, 최적화할 수 있다. 2개의 평균선의 파라미터와 인수를 포함하고, 최적화함으로써 최적의 파라미터 조합을 찾을 수 있다.
스케줄 가능, 자동화 거래에 적합. 전략 논리는 간단하고 명확하며, 실행 빈도는 높으며, 자동 거래를 구현하기 위해 매우 적합하다.
제어 가능한 위험, 손해 중지 메커니즘. 이동식 손해 중지 또는 수적 손해 중지 설정이 가능하며, 단일 손실을 제어할 수 있다.
하지만 이 전략에는 몇 가지 위험도 있습니다.
쌍평평선 교차는 지연에 있다. 평평선은 그 자체로 가격보다 지연되어 있고, 교차가 발생했을 때 트렌드는 이미 한동안 반전되어 있었을 것이다.
트렌드 반전이 지속될 수 있는 것은 아니며, 곧 다시 반전될 수 있으며, 덫을 놓을 수 있다.
철회는 여전히 존재합니다. 단독 손실을 줄일 수 있지만, 연속적으로 철회하는 것은 더 큰 철회로 이어질 수 있습니다.
데이터 최적화 위험. 과도한 최적화 변수, 역사 데이터에서 좋은 성능을 보이지만 실 디스크 효과는 좋지 않다.
위험을 대응하는 해결책은 다음과 같습니다.
패러미터를 최적화하여 신속한 응답을 위한 평행선 설정을 찾습니다.
다른 지표와 결합하여 감금되는 것을 피하십시오.
연쇄 손실을 줄이기 위해 중지 위치를 조정하십시오.
다중 집합 파라미터 최적화 테스트, 파라미터 강도를 평가한다.
이중 평행선 역전 전략은 다음과 같은 측면에서 최적화될 수 있다:
다른 종류의 평균선을 테스트하여 반응이 더 민감한 평균선을 찾습니다. 카마, ZLEMA 등
평균선 변수를 최적화하여 최적의 길이 조합을 찾습니다. 일반적으로 짧은 주기의 평균선 효과가 더 좋습니다.
다른 데이터 소스를 테스트합니다. 예를 들어, 종식 가격, 평균 가격, 전형적인 가격 등
트렌드 필터를 추가하여 부적절한 역전 신호를 피한다. Donchian 채널 등이 사용된다.
다른 지표와 결합하여 확인합니다. 예를 들어, 수량 가격 지표 MACD, OBV 등.
이동 상쇄, 계좌 최대 손실 등과 같은 위험 관리 장치를 추가하십시오.
포트폴리오를 최적화하고, 최적의 자산 분배 비율을 찾습니다.
매개 변수 튼튼성 테스트를 추가하여 매개 변수 오버 최적화 위험을 평가한다.
쌍평평선 역전 전략은 시장의 단기 역전을 포착하는 데 적합한 간단한 실용적인 단선 전략이다. 이 전략은 회전이 작고, 실행하기 쉽고, 양적 거래에 적합하다. 하지만, 지연, 포획 등의 위험과 같은 몇 가지 문제가 있습니다.
/*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()