Estratégia de busca de tendências com laser duplo

Autora:ChaoZhang, Data: 2023-11-06 10:01:42
Tags:

img

Resumo

Esta estratégia usa Bandas de Bollinger, Canais de Keltner e Índice de Força Relativa Adaptativa para determinar a direção da tendência atual, combinada com SAR Parabólico para cronometrar a entrada. Os sinais de negociação são gerados quando os julgamentos desses três indicadores concordam. A estratégia julga principalmente a direção da tendência e entra em tempo hábil quando a tendência muda, visando lucro.

Princípios

Esta estratégia combina os seguintes três indicadores técnicos para determinar a tendência actual:

  1. Indicador de Momento Squeeze: Calcula Bandas de Bollinger e Canais de Keltner. Quando as duas bandas se sobrepõem, ele gera um aperto e sinaliza uma mudança de tendência iminente. Retorna o estado de aperto e a inclinação de regressão linear.

  2. RSI ponderado por volume: Calcula o RSI ponderado por volume. Usa o ponto médio para determinar os níveis de sobrecompra / sobrevenda. Enfatiza as mudanças de volume.

  3. SAR parabólico: julga a localização do preço atual em relação à linha SAR. SAR acima do preço indica tendência de queda, enquanto SAR abaixo do preço indica tendência de alta.

A estratégia usa bandas de Bollinger para determinar a direção da tendência, canais de Keltner para refiná-la, RSI para encontrar oportunidades de reversão quando sobrecomprado/supervendido e SAR para cronometrar a entrada.

  1. Calcule as bandas de Bollinger, os canais de Keltner, o indicador de compressão.

  2. Calcule o RSI ponderado pelo volume. RSI acima do ponto médio indica tendência de alta, abaixo do ponto médio tendência de queda.

  3. Calcule SAR Parabólico. SAR abaixo do preço mostra tendência de alta, acima do preço mostra tendência de queda.

  4. Combine os três indicadores: quando o aperto acontece, o RSI vai acima do ponto médio, SAR está abaixo do preço, um sinal longo é gerado.

  5. Quando um sinal é acionado, verifique se os julgamentos dos três indicadores na barra anterior são o oposto do sinal atual.

  6. Configure o stop loss e tire lucro após a entrada, seguindo o stop loss.

Vantagens

As vantagens desta estratégia:

  1. A combinação de múltiplos indicadores melhora a precisão do julgamento da tendência.

  2. A lógica do indicador é simples e fácil de entender.

  3. A confirmação de múltiplos indicadores ajuda a filtrar falhas.

  4. O mecanismo de stop loss e take profit bloqueia os lucros e limita os riscos.

  5. Os dados de backtest extensivos garantem a fiabilidade.

Riscos

Há também alguns riscos:

  1. A lógica de entrada longa e curta é semelhante e pode gerar sinais conflitantes.

  2. Todos os indicadores usam otimização de parâmetros, riscos de sobreajuste.

  3. Alta frequência de negociação, dimensão de posição precisa de controlo.

  4. O stop loss pode estar muito perto e ser facilmente interrompido.

Soluções:

  1. Adicionar um controlo de persistência dos juízos dos indicadores para evitar oscilações do sinal.

  2. Utilize a análise de avanço para ajustar os parâmetros e evitar o sobreajuste.

  3. Configure o tamanho da pirâmide para controlar posições por direção.

  4. Teste diferentes intervalos de stop loss para otimizar o preço de stop loss.

Orientações de otimização

Algumas orientações para otimizar a estratégia:

  1. Otimizar os parâmetros do indicador para estabilidade.

  2. Adicione a lógica de dimensionamento de posição como percentagem fixa/igual.

  3. Teste diferentes métodos de stop loss, como volatilidade ou paradas lineares, posições de zero, etc.

  4. Adicione a gestão de dinheiro como o dimensionamento de posição fracionária fixa.

  5. Usar modelos de aprendizagem de máquina para entrada e saída dinâmicas.

  6. Adicionar mecanismos de cobertura, tanto a longo como a curto prazo, para reduzir os riscos sistémicos correlacionados.

  7. Considerar mais indicadores e criar mecanismos de votação para melhorar a precisão.

Conclusão

A estratégia tem uma lógica clara de usar múltiplos indicadores para determinar a direção da tendência e entrar astutamente no aperto. A mecânica de stop loss e take profit limita os riscos. A otimização de parâmetros e os controles de risco podem melhorar ainda mais os resultados do backtest e dos resultados ao vivo.


/*backtest
start: 2023-10-06 00:00:00
end: 2023-11-05 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © XaviZ

//#####©ÉÉÉɶN###############################################
//####*..´´´´´´,,,»ëN########################################
//###ë..´´´´´´,,,,,,''%©#####################################
//###'´´´´´´,,,,,,,'''''?¶###################################
//##o´´´´´´,,,,,,,''''''''*©#################################
//##'´´´´´,,,,,,,'''''''^^^~±################################
//#±´´´´´,,,,,,,''''''''^í/;~*©####æ%;í»~~~~;==I±N###########
//#»´´´´,,,,,,'''''''''^;////;»¶X/í~~/~~~;=~~~~~~~~*¶########
//#'´´´,,,,,,''''''''^^;////;%I^~/~~/~~~=~~~;=?;~~~~;?ë######
//©´´,,,,,,,''''''''^^~/////X~/~~/~~/~~»í~~=~~~~~~~~~~^;É####
//¶´,,,,,,,''''''''^^^;///;%;~/~~;í~~»~í?~?~~~?I/~~~~?*=íÑ###
//N,,,,,,,'''''''^^^^^///;;o/~~;;~~;£=»í»;IX/=~~~~~~^^^^'*æ##
//#í,,,,,''''''''^^^^^;;;;;o~»~~~~íX//~/»~;í?IíI»~~^/*?'''=N#
//#%,,,'''''''''^^^^^^í;;;;£;~~~//»I»/£X/X/»í*&~~~^^^^'^*~'É#
//#©,,''''''''^^^^^^^^~;;;;&/~/////*X;í;o*í»~=*?*===^'''''*£#
//##&''''''''^^^^^^^^^^~;;;;X=í~~~»;;;/~;í»~»±;^^^^^';=''''É#
//##N^''''''^^^^^^^^^^~~~;;;;/£;~~/»~~»~~///o~~^^^^''''?^',æ#
//###Ñ''''^^^^^^^^^^^~~~~~;;;;;í*X*í»;~~IX?~~^^^^/?'''''=,=##
//####X'''^^^^^^^^^^~~~~~~~~;;íííííí~~í*=~~~~Ií^'''=''''^»©##
//#####£^^^^^^^^^^^~~~~~~~~~~~íííííí~~~~~*~^^^;/''''='',,N###
//######æ~^^^^^^^^~~~~~~~~~~~~~~íííí~~~~~^*^^^'=''''?',,§####
//########&^^^^^^~~~~~~~~~~~~~~~~~~~~~~~^^=^^''=''''?,íN#####
//#########N?^^~~~~~~~~~~~~~~~~~~~~~~~~^^^=^''^?''';í@#######
//###########N*~~~~~~~~~~~~~~~~~~~~~~~^^^*'''^='''/É#########
//##############@;~~~~~~~~~~~~~~~~~~~^^~='''~?'';É###########
//#################É=~~~~~~~~~~~~~~^^^*~'''*~?§##############
//#####################N§£I/~~~~~~»*?~»o§æN##################

//@version=4
strategy(title="M-SQUEEZE", overlay = true)

//study(title="M-SQUEEZE", overlay = true)

src = input(close, "SOURCE", type = input.source)

// ███▓▒░░ VARIABLES ░░▒▓███

var bool longCond = na, var bool shortCond = na
var int CondIni_long0 = 0, var int CondIni_short0 = 0
var int CondIni_long = 0, var int CondIni_short = 0
var float last_open_longCondition = na, var float last_open_shortCondition = na
var int last_longCondition0 = na, var int last_shortCondition0 = na
var int last_longCondition = na, var int last_shortCondition = na
var bool long_tp = na, var bool short_tp = na
var int last_long_tp = na, var int last_short_tp = na
var bool Final_Long_tp = na, var bool Final_Short_tp = na
var bool SMI_longCond = na, var bool SMI_shortCond = na
var bool RSI_longCond = na, var bool RSI_shortCond = na
var bool ADX_longCond = na, var bool ADX_shortCond = na
var bool SAR_longCond = na, var bool SAR_shortCond = na
var bool Final_longCondition0 = na, var bool Final_shortCondition0 = na
var bool Final_longCondition = na, var bool Final_shortCondition = na

// ███▓▒░░ SQUEEZE MOMENTUM INDICATOR ░░▒▓███

Act_SMI = input(true, "SQUEEZE MOMENTUM INDICATOR")
BB_length = input(85, title="BOLLINGER BANDS LENGTH", minval = 1)
BB_mult = input(2.1, title="BOLLINGER BANDS MULTI-FACTOR", minval = 0.1, step = 0.1)
KC_length = input(38, title="KELTNER CHANNEL LENGTH", minval = 1)
KC_mult = input(2.0, title="KELTNER CHANNEL MULTI-FACTOR", minval = 0.1, step = 0.1)

SQUEEZE_M(_src,_BB_length,_BB_mult,_KC_length,_KC_mult)=>

    // Calculate BB
    basis = sma(_src, _BB_length)
    dev = _BB_mult * stdev(_src, _BB_length)
    upperBB = basis + dev
    lowerBB = basis - dev
    // Calculate KC
    ma = sma(src, _KC_length)
    rangema = sma(tr, _KC_length)
    upperKC = ma + rangema * _KC_mult
    lowerKC = ma - rangema * _KC_mult
    // Squeeze
    sqzOn = lowerBB > lowerKC and upperBB < upperKC
    sqzOff = lowerBB < lowerKC and upperBB > upperKC
    nosqz = sqzOn == false and sqzOff == false
    // Linear Regression curve
    val = linreg(_src - avg(avg(highest(high, _KC_length), lowest(low, _KC_length)), sma(close, _KC_length)), _KC_length, 0)
    [nosqz,val]
    
[NOSQZ,VAL] = SQUEEZE_M(src,BB_length,BB_mult,KC_length,KC_mult)

barcolor(iff(VAL > 0, iff(VAL > nz(VAL[1]), color.lime, color.green), iff(VAL < nz(VAL[1]), color.red, color.maroon)))

// ███▓▒░░ SAR ░░▒▓███

Act_SAR = input(true, "PARABOLIC SAR")
Sst = input (0.73, "SAR STAR", step=0.01, minval = 0.01)
Sinc = input (0.5, "SAR INC", step=0.01, minval = 0.01)
Smax = input (0.06, "SAR MAX", step=0.01, minval = 0.01)

SAR = sar(Sst, Sinc, Smax)
plot(SAR, style = plot.style_cross, title = "SAR")

// ███▓▒░░ RSI VOLUME WEIGHTED ░░▒▓███

Act_RSI = input(true, "RSI VOLUME WEIGHTED")
RSI_len = input(22, "RSI LENGHT", minval = 1)
RSI_obos = input(45,title="RSI CENTER LINE", type=input.integer, minval = 1)

WiMA(_src, _length)=> 
    var float MA_s=0.0
    MA_s:=(_src + nz(MA_s[1] * (_length-1)))/_length
    MA_s

RSI_Volume(fv, length)=>	
	up=iff(fv>fv[1],abs(fv-fv[1])*volume,0)
	dn=iff(fv<fv[1],abs(fv-fv[1])*volume,0)
	upt=WiMA(up,length)
	dnt=WiMA(dn,length)
	100*(upt/(upt+dnt))

RSI_V = RSI_Volume(src, RSI_len)

// ███▓▒░░ STRATEGY ░░▒▓███

SMI_longCond := (Act_SMI ? (VAL > 0 and (VAL > nz(VAL[1])) and not NOSQZ) : RSI_longCond) 
RSI_longCond := (Act_RSI ? (RSI_V > RSI_obos) : SAR_longCond)
SAR_longCond := (Act_SAR ? (SAR < close) : SMI_longCond)

SMI_shortCond := (Act_SMI ? (VAL < 0 and (VAL < nz(VAL[1])) and not NOSQZ) : RSI_shortCond) 
RSI_shortCond := (Act_RSI ? (RSI_V < RSI_obos) : SAR_shortCond)
SAR_shortCond := (Act_SAR ? (SAR > close) : SMI_shortCond)

longCond := SMI_longCond and RSI_longCond and SAR_longCond
shortCond := SMI_shortCond and RSI_shortCond and SAR_shortCond

CondIni_long0 := longCond ? 1 : shortCond ? -1 : CondIni_long0[1]
CondIni_short0 := longCond ? 1 : shortCond ? -1 : CondIni_short0[1]

longCondition0 = (longCond and CondIni_long0[1] == -1)
shortCondition0 = (shortCond and CondIni_short0[1] == 1)

CondIni_long := longCond[1] ? 1 : shortCond[1] ? -1 : CondIni_long[1]
CondIni_short := longCond[1] ? 1 : shortCond[1] ? -1 : CondIni_short[1]

longCondition = (longCond[1] and CondIni_long[1] == -1)
shortCondition = (shortCond[1] and CondIni_short[1] == 1)

// ███▓▒░░ ALERTS & SIGNALS ░░▒▓███

plotshape(longCondition, title = "Long Signal", style = shape.triangleup, location = location.belowbar, color = color.blue, transp = 0, size = size.tiny)
plotshape(shortCondition, title = "Short Signal", style = shape.triangledown, location = location.abovebar, color = #FF0000, transp = 0, size = size.tiny)

//alertcondition(longCondition, title="Long Alert", message = "LONG") 
//alertcondition(shortCondition, title="Short Alert", message = "SHORT")

// ███▓▒░░ BACKTESTING ░░▒▓███

testStartYear = input(2018, "BACKTEST START YEAR", minval = 1980, maxval = 2222) 
testStartMonth = input(01, "BACKTEST START MONTH", minval = 1, maxval = 12)
testStartDay = input(01, "BACKTEST START DAY", minval = 1, maxval = 31)
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,0,0)
testStopYear = input(2222, "BACKTEST STOP YEAR", minval=1980, maxval = 2222)
testStopMonth = input(12, "BACKTEST STOP MONTH", minval=1, maxval=12)
testStopDay = input(31, "BACKTEST STOP DAY", minval=1, maxval=31)
testPeriodStop = timestamp(testStopYear, testStopMonth, testStopDay, 0, 0)

testPeriod = time >= testPeriodStart and time <= testPeriodStop ? true : false

strategy.entry("Long", strategy.long, when = longCondition0 and testPeriod)
strategy.entry("Short", strategy.short, when = shortCondition0 and testPeriod)


Mais.