Estratégia de reversão da média móvel dupla

Autora:ChaoZhang, Data: 2023-11-17 16:56:24
Tags:

img

Resumo

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.

Estratégia lógica

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.

Análise das vantagens

As principais vantagens da Estratégia de Reversão de MA Dupla são:

  1. As médias móveis rápidas podem capturar rapidamente reversões de curto prazo com drawdowns menores.

  2. O cruzamento de dois MAs gera sinais comerciais claros.

  3. Muito configurável com múltiplos parâmetros ajustáveis.

  4. 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.

  5. Risco controlado com mecanismo de stop loss. movendo stop loss ou valor stop loss pode limitar a perda de uma única negociação.

Análise de riscos

Há também alguns riscos da estratégia:

  1. 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.

  2. Risco de transacções com serralheira. A tendência invertida pode rapidamente reverter novamente, causando perdas consecutivas.

  3. Embora o stop loss limite a perda única, o stop loss consecutivo ainda pode levar a grandes drawdowns.

  4. 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:

  1. Optimize os parâmetros para encontrar MAs mais rápidos.

  2. Adicione filtros, como indicadores de volume e volatilidade, para evitar negociações de fenda.

  3. Ajustar a posição de stop loss para reduzir a probabilidade de uma stop loss consecutiva.

  4. Teste de robustez dos conjuntos de parâmetros para avaliar os riscos de sobreajuste.

Orientações para melhorias

A estratégia pode ser ainda melhorada nos seguintes aspectos:

  1. Teste diferentes tipos de MA para encontrar os mais sensíveis, como KAMA, ZLEMA etc.

  2. Optimize os comprimentos MA para encontrar a combinação ideal.

  3. Teste diferentes fontes de dados, como preço de fechamento, preço médio, preço típico, etc.

  4. Adicionar um filtro de tendência para evitar sinais de reversão inadequados, como o canal de Donchian.

  5. Adicionar outros indicadores de confirmação, como MACD, OBV, etc.

  6. Melhorar os mecanismos de gestão de riscos, como a movimentação de stop loss, perda máxima da conta, etc.

  7. Optimização da carteira para encontrar a melhor alocação de ativos.

  8. Teste de robustez dos parâmetros para avaliar os riscos de sobreajuste.

Conclusão

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()

Mais.