
A estratégia de reversão de média móvel dupla é uma estratégia típica de reversão de curto prazo. A estratégia usa duas linhas de média com diferentes configurações de parâmetros para emitir sinais de negociação e obter lucros quando a tendência se reverte.
A estratégia usa duas linhas de equilíbrio para a geração de sinais de negociação. A primeira linha de equilíbrio maopening é usada para determinar a direção da tendência, e a segunda linha de equilíbrio maclosing é usada para emitir sinais de negociação.
Quando o maopening sobe, indica que está em fase de tendência ascendente; quando o maopening desce, indica que está em fase de tendência descendente. O maclosing é multiplicado por um fator maior que 1, o que o torna mais sensível e pode emitir sinais de reversão antecipadamente.
Especificamente, quando o maopening sobe e o maclosing desce o maopening, a estratégia abre uma posição a zero, indicando uma reversão de tendência; quando o maopening desce e o maclosing desce o maopening, indicando uma reversão de tendência, a estratégia abre uma posição a mais.
Os parâmetros da estratégia incluem o tipo de linha média, o comprimento, a fonte de dados, etc. Os parâmetros podem ser ajustados para obter melhores efeitos de negociação. Além disso, a estratégia também possui algumas opções embutidas, como o modo de abrir posições, o modo de parar perdas, etc., que podem ser ajustadas conforme necessário.
Os principais benefícios da estratégia de inversão de dupla linha de equilíbrio incluem:
Pequena retração, adequada para negociação de linha curta. Usando duas linhas médias rápidas, pode-se capturar rapidamente a reversão da tendência de curto prazo, sendo a retração menor.
É simples e fácil de entender. A interseção de duas linhas uniformes é um sinal de transação, muito simples e claro.
Há muitos parâmetros ajustáveis que podem ser otimizados. Parâmetros e coeficientes que contêm duas medianas podem ser otimizados para encontrar a melhor combinação de parâmetros.
Programabilidade, adequada para negociação automática. A lógica da estratégia é simples e clara, a frequência de execução é alta, ideal para a programação de negociação automática.
Risco controlado, com um mecanismo de parada de perdas. Pode ser configurado para parar de perda móvel ou de perda numérica, pode controlar a perda individual.
A estratégia de inversão de dupla linha de equilíbrio também apresenta alguns riscos:
A dupla linha de equilíbrio está em atraso. A linha de equilíbrio está atrasada em relação ao preço, e a tendência pode ter sido revertida por algum tempo quando a cruz ocorreu.
É fácil de ser enganado. A reversão de tendência não é necessariamente duradoura e pode voltar a acontecer em breve, criando uma armadilha.
As retiradas continuam a existir. O congelamento atempado pode reduzir as perdas individuais, mas o congelamento contínuo também pode causar uma retirada maior.
Risco de otimização de dados. Parâmetros de otimização excessiva, com bom desempenho em dados históricos, mas com má eficácia em disco real.
As soluções para os riscos incluem:
Parâmetros de otimização para encontrar configurações de linha média de resposta rápida.
Combinado com outros indicadores, como o indicador de preço de quantidade, o indicador de volatilidade, etc.
Ajustar a posição de parada para reduzir a probabilidade de parada contínua.
Testes de otimização de múltiplos parâmetros para avaliar a robustez dos parâmetros.
A estratégia de inversão de dupla equilíbrio pode ser otimizada nos seguintes aspectos:
Teste diferentes tipos de médias, procurando médias mais sensíveis à reação, como Kama, ZLEMA, etc.
Otimizar os parâmetros da linha média para encontrar a melhor combinação de comprimentos. Geralmente, a linha média de menor período é mais eficaz.
Teste diferentes fontes de dados, como preço de fechamento, preço médio, preço típico, etc.
Aumentar o filtro de tendência para evitar sinais de inversão inadequados.
Confirmação em combinação com outros indicadores, como MACD, OBV, etc.
Aumentar os mecanismos de gestão de riscos, como o stop loss móvel, o máximo de perdas na conta, etc.
Optimizar o portfólio para encontrar a melhor proporção de distribuição de ativos.
Adicionar testes de robustez de parâmetros para avaliar o risco de otimização de parâmetros.
A estratégia de inversão de linha dupla é uma estratégia de linha curta simples e prática, adequada para capturar a reversão de curto prazo do mercado. A estratégia de retração é pequena, fácil de implementar e ideal para negociação quantitativa. Mas também há alguns problemas, como risco de atraso, bloqueio e outros.
/*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()