A estratégia de reversão de média móvel dupla é uma estratégia típica de reversão de média de curto prazo.
A estratégia usa duas médias móveis para gerar sinais de negociação. A primeira MA maopening é usada para determinar a direção da tendência. A segunda MA maclosing é usada para gerar sinais de negociação.
Quando a maopening sobe, indica que o mercado atual está em uma tendência de alta. Quando a maopening desce, indica que o mercado atual está em uma tendência de queda. o maclosing é multiplicado por um coeficiente maior que 1 para torná-lo mais sensível para gerar sinais de reversão precoces.
Especificamente, quando o maopening sobe e o maclosing cruza abaixo do maopening, indica uma inversão de tendência. A estratégia abrirá uma posição curta. Quando o maopening desce e o maclosing cruza acima do maopening, indica uma inversão de tendência. A estratégia abrirá uma posição longa.
Os parâmetros da estratégia incluem tipo de MA, comprimento, fonte de dados, etc. O desempenho comercial pode ser otimizado ajustando esses parâmetros.
As principais vantagens da Estratégia de Reversão de MA Dupla são:
As médias móveis rápidas podem capturar rapidamente reversões de curto prazo com drawdowns menores.
O cruzamento de dois MAs gera sinais comerciais claros.
Muito configurável com múltiplos parâmetros ajustáveis.
Fácil de automatizar com fluxo lógico claro. A lógica simples e a negociação de alta frequência tornam-no muito adequado para negociação automatizada.
Risco controlado com mecanismo de stop loss. movendo stop loss ou valor stop loss pode limitar a perda de uma única negociação.
Há também alguns riscos da estratégia:
O retardo dos sinais de cruzamento de MA. Os próprios MA ficam para trás do preço. O cruzamento pode acontecer depois que a tendência tenha se invertido por algum tempo.
Risco de transacções com serralheira. A tendência invertida pode rapidamente reverter novamente, causando perdas consecutivas.
Embora o stop loss limite a perda única, o stop loss consecutivo ainda pode levar a grandes drawdowns.
Risco de sobreajuste: a otimização excessiva dos parâmetros pode levar a sobreajuste e mau desempenho na negociação ao vivo.
As soluções incluem:
Optimize os parâmetros para encontrar MAs mais rápidos.
Adicione filtros, como indicadores de volume e volatilidade, para evitar negociações de fenda.
Ajustar a posição de stop loss para reduzir a probabilidade de uma stop loss consecutiva.
Teste de robustez dos conjuntos de parâmetros para avaliar os riscos de sobreajuste.
A estratégia pode ser ainda melhorada nos seguintes aspectos:
Teste diferentes tipos de MA para encontrar os mais sensíveis, como KAMA, ZLEMA etc.
Optimize os comprimentos MA para encontrar a combinação ideal.
Teste diferentes fontes de dados, como preço de fechamento, preço médio, preço típico, etc.
Adicionar um filtro de tendência para evitar sinais de reversão inadequados, como o canal de Donchian.
Adicionar outros indicadores de confirmação, como MACD, OBV, etc.
Melhorar os mecanismos de gestão de riscos, como a movimentação de stop loss, perda máxima da conta, etc.
Optimização da carteira para encontrar a melhor alocação de ativos.
Teste de robustez dos parâmetros para avaliar os riscos de sobreajuste.
A reversão de MA dupla é uma estratégia de negociação de curto prazo simples e prática. É adequada para capturar reversões de curto prazo com negociação quantitativa. No entanto, existem riscos como atrasos e negociações de fenda. A estratégia pode ser melhorada por otimização de parâmetros, adição de filtros, aumento do controle de risco, etc. para desenvolver uma estratégia estável e eficiente com bom desempenho comercial real.
/*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()