A estratégia visa capturar as fortes tendências no mercado de criptomoedas, usando múltiplos canais e médias móveis para identificar os sinais de formação de tendências, e combinando a capacidade de filtragem quantitativa para detectar brechas falsas, enquanto usa um stop-loss adaptativo para bloquear ganhos, que podem ser obtidos em mercados em tendência.
A estratégia usa uma combinação de canais rápidos, canais lentos e médias móveis rápidas para identificar tendências. A configuração dos parâmetros de canais rápidos é mais sensível, para capturar oscilações de preços de curto prazo; os parâmetros de canais lentos são mais suaves, para julgar as grandes tendências; os parâmetros de médias móveis rápidas são intermediários entre os dois, gerando um sinal de negociação quando eles atravessam o canal.
Concretamente, ele primeiro calcula o trajeto ascendente e descendente do canal rápido, bem como a média móvel. Quando o preço quebra o trajeto ascendente, se o trajeto descendente do canal lento também estiver acima da média móvel, gerará um sinal de parada. Por outro lado, ao romper o trajeto descendente, determine se o trajeto do canal lento está abaixo da média móvel ou não, gerando um sinal de parada.
Além disso, ele detecta a forma de K-linhas, que requerem que várias K-linhas sejam ordenadas para filtrar brechas falsas; e calcula um indicador de taxa de variação de preços, evitando que o mercado fique preso em uma oscilação dentro do canal; Adicione um indicador de volume de transação para garantir que o tempo de ruptura possa acompanhar.
No que diz respeito ao stop loss, a estratégia usa um stop loss adaptativo. De acordo com a volatilidade do período mais recente, o stop loss é ajustado dinamicamente. Isso permite, ao mesmo tempo em que garante o stop loss, retroceder o máximo possível ao cenário de tendência.
A maior vantagem da estratégia é que as regras de julgamento para a formação de sinais de negociação são mais rigorosas e podem filtrar de forma eficaz as falsas rupturas não tendenciais, capturando verdadeiramente os pontos de mudança de tendência do mercado.
A combinação de múltiplos canais e médias móveis, com padrões de julgamento mais rigorosos, reduz a probabilidade de julgamento errado.
A linha K é verificada em ordem, evitando que uma única linha K inativa produza um sinal errado.
Em combinação com os indicadores de variação de preços, pode-se determinar se a correção está em andamento ou não, evitando perder oportunidades de reversão.
A adição do indicador de energia quantitativa julga que apenas a quantidade com o preço irá gerar um sinal, evitando a ruptura ineficaz.
O mecanismo de parada de perda adaptável permite o bloqueio máximo dos lucros da tendência, desde que a parada de perda seja garantida.
Portanto, a estratégia, em geral, possui características como otimização de configuração, rigor de decisão e auto-adaptação de parada de prejuízo, o que é ideal para capturar as tendências.
Embora a estratégia tenha sido bastante aperfeiçoada para filtrar as tendências de invasão e interceptação, ainda há alguns riscos a serem observados:
A configuração de parâmetros é muito complexa, as combinações de parâmetros variam muito, é necessário encontrar o parâmetro ideal após um grande número de testes, e a configuração incorreta pode gerar muitos sinais errados.
As médias rápidas e os intervalos de passagem de horas de um canal são propensos a gerar posições abertas e fechadas com frequência, o que é prejudicial para a sustentação de tendências de seguimento.
A suspensão de perda do mecanismo de suspensão de perda adaptável é calculada com base no diferencial padrão simples, que pode ser muito pequeno para situações extremas.
A dependência excessiva em indicadores técnicos dificulta a resposta a mudanças fundamentais.
A estratégia é uma estratégia de acompanhamento de tendências, que tem um desempenho mais fraco em mercados de balanço.
Para combater estes riscos, recomenda-se que se tomem as seguintes medidas:
Faça um retrospecto completo para determinar a melhor combinação de parâmetros, e considere o uso de métodos como aprendizado de máquina para otimização de parâmetros.
A liberação apropriada do intervalo de canais e o período de média móvel também podem ser apropriadamente prolongados, reduzindo a frequência desnecessária de abertura de armazenamento.
Pode-se considerar a introdução de modelos mais avançados de cálculo da taxa de flutuação, como os fundos de cobertura.
Leia as informações básicas e evite negociar apenas com indicadores técnicos.
Aumentar o julgamento sobre o estado do mercado e suspender a negociação em mercados em turbulência.
A estratégia também pode ser melhorada em alguns aspectos:
Adicionar algoritmos de aprendizagem de máquina para otimizar automaticamente os parâmetros. Pode registrar o desempenho dos parâmetros em diferentes ambientes de mercado, criar tabelas de consulta e otimizar dinamicamente.
Aumentar o julgamento sobre o estado do mercado, como aumentar o julgamento de que a situação é uma tendência ou um módulo de turbulência, suspender a negociação em mercados turbulentos e evitar perdas desnecessárias.
Optimizar a estratégia de parada de perdas, você pode considerar outras formas de parada de perdas, como parada de rastreamento, parada proporcional.
Adicionar fatores fundamentais, emitir alertas quando ocorrem eventos fundamentais importantes, para evitar perdas com base apenas em indicadores técnicos.
Otimizar o portfólio, combinando a estratégia com outros portfólios de estratégias não relevantes, pode disseminar ainda mais o risco.
A integração de uma estrutura de negociação quantitativa, a execução automática de sinais e o controle rigoroso de riscos.
Em suma, a estratégia é, em geral, muito adequada para capturar oportunidades de tendências no mercado de criptomoedas. Ela usa múltiplos canais e médias móveis para gerar sinais de negociação e efetivamente filtra o ruído de falsas rupturas, bloqueando com sucesso os lucros da tendência.
/*backtest
start: 2022-09-21 00:00:00
end: 2023-09-27 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=4
strategy("Extremely Overfit", overlay=true, commission_type=strategy.commission.percent, commission_value=.16, default_qty_type=strategy.percent_of_equity, default_qty_value=100, pyramiding = 1)
price = close
goLong = input(title="go long?", type=input.bool, defval=true)
goShort = input(title="go short?", type=input.bool, defval=true)
//trendRestrict = input(title="basic trend restriction?", type=input.bool, defval=false)
dynamicRestrict = true //input(title="dynamic trend restriction?", type=input.bool, defval=true)
longtrendimpt = true //input(title="additional weight on long-term trends?", type=input.bool, defval=true)
volRestrict = true //input(title="volume restriction?", type=input.bool, defval=true)
conservativeClose = false //input(title="conservative order closing?", type=input.bool, defval=false)
Restrictiveness = input ( -40,step=10,title ="Restrictiveness (higher = make fewer trades)")
volatilityImportance = 3.2 //input( 3.2, step = 0.1, minval = 0)
fastChannelLength = input( 6 )
fastChannelMargin = input ( 3.2, step = 0.1, minval = 0)
slowChannelLength = input ( 6, step = 1, minval = 0)
slowChannelMargin = input ( 1.5, step = 0.1, minval = 0)
fastHMAlength = input (4, step = 1, minval = 0)
stopLoss = input( 3, step = 0.1, minval = 0)
//altClosePeriod = input( 27, step = 1, minval = 1)
//altCloseFactor = input( 4.9, step = 0.1)
stopLossFlexibility = 50 //input(50, step=10, title="effect of volatility on SL?")
volumeMAlength = 14 //input ( 14, step = 1, minval = 1)
volumeVolatilityCutoff = 3.8 // ( 3.8, step = 1, minval = 0)
trendSensitivity = 3.8 //input ( 3.8, step = 0.1)
obvLookback = 10 //input(10, step = 10, minval = 10)
obvCorrThreshold = 0.89 //input(0.89, step = 0.01)
ROClength = 80 //input( 80, step = 10)
ROCcutoff = 5.6 //input( 5.6, step=0.1)
trendRestrict = false
//trendLookback = input ( 360, step = 10, minval = 10)
//longTrendLookback = input(720, step = 10, minval = 10)
//longTrendImportance = input(1.5, step = 0.05)
trendLookback = 360
longTrendLookback = 720
longTrendImportance = 1.5
//conservativeness = input( 2.4, step = 0.1)
conservativeness = 0
//trendPower = input( 0, step=1)
trendPower = 0
//conservativenessLookback = input( 650, step = 10, minval = 0)
conservativenessLookback = 10
//consAffectFactor = input( 0.85,step=0.01)
consAffectFactor = 0.85
//volatilityLookback = input(50, step=1, minval=2)
volatilityLookback = int(50)
recentVol = stdev(price,volatilityLookback)/sqrt(volatilityLookback)
//price channel
fastChannel = ema(price, fastChannelLength)
fastChannelUB = fastChannel * (1 + (float(fastChannelMargin) / 1000)) + (recentVol * (float(volatilityImportance) * (1 + (Restrictiveness/100))))
fastChannelLB = fastChannel * (1 - (float(fastChannelMargin) / 1000)) - (recentVol * (float(volatilityImportance) * (1 + (Restrictiveness/100))))
fchU = ((fastChannelUB < open) and (fastChannelUB < close))
fchL = ((fastChannelLB > open) and (fastChannelLB > close))
//plot(fastChannelUB)
//plot(fastChannelLB)
//slow channel
//slowChannelLBmargin = input ( 2, step = 0.1, minval = 0 )
slowChannel = ema(ema(price,slowChannelLength),slowChannelLength)
slowChannelUB = slowChannel * (1 + (float(slowChannelMargin) / 2000)) + (recentVol * (float(volatilityImportance) * (1 + (Restrictiveness/100))))
slowChannelLB = slowChannel * (1 - (float(slowChannelMargin) / 2000)) - (recentVol * (float(volatilityImportance) * (1 + (Restrictiveness/100))))
schU = ((slowChannelUB < close))
schL = ((slowChannelLB > close))
cschU = (((slowChannelUB * (1 + conservativeness)) < close))
cschL = (((slowChannelUB * (1 - conservativeness)) > close))
//plot(slowChannel,color = #00FF00)
//plot(slowChannelUB,color = #00FF00)
//plot(slowChannelLB,color = #00FF00)
fastHMA = hma(price,fastHMAlength)
fastAboveUB = (fastHMA > slowChannelUB)
fastBelowLB = (fastHMA < slowChannelLB)
//plot(fastHMA, color = #FF0000, linewidth = 2)
//consecutive candles
//consecutiveCandlesReq = input(1, step = 1, minval = 1, maxval = 4)
consecutiveCandlesReq = 1
consecutiveBullReq = float(consecutiveCandlesReq)
consecutiveBearReq = float(consecutiveCandlesReq)
cbull = ((close[0] > close[1]) and (consecutiveBullReq == 1)) or (((close[0] > close[1]) and (close[1] > close[2])) and consecutiveBullReq == 2) or (((close[0] > close[1]) and (close[1] > close[2]) and (close[2] > close[3])) and consecutiveBullReq == 3) or (((close[0] > close[1]) and (close[1] > close[2]) and (close[2] > close[3]) and (close[3] > close[4])) and consecutiveBullReq == 4)
cbear = ((close[0] < close[1]) and (consecutiveBearReq == 1)) or (((close[0] < close[1]) and (close[1] < close[2])) and consecutiveBearReq == 2) or (((close[0] < close[1]) and (close[1] < close[2]) and (close[2] < close[3])) and consecutiveBearReq == 3) or (((close[0] < close[1]) and (close[1] < close[2]) and (close[2] < close[3]) and (close[3] < close[4])) and consecutiveBearReq == 4)
//trend detection
//trendCutoff = input(0, step = 0.1)
trendCutoff = 0
trendDetectionPct = float(trendCutoff/100)
trendVal = float((close[0] - close[trendLookback])/close[0])
trendUp = (trendVal > (0 + trendDetectionPct))
trendDown = (trendVal < (0 - trendDetectionPct))
//plot(trendVal+36.5,linewidth=2)
// peak indicators
peakHigh = ((fastHMA > fastChannelUB) and (fastChannelLB > slowChannelUB))
peakLow = ((fastHMA < fastChannelLB) and (fastChannelUB < slowChannelLB))
TpeakHigh = (fastHMA > fastChannelUB) and (fastChannelUB > slowChannelUB)
TpeakLow = (fastHMA < fastChannelUB) and (fastChannelLB < slowChannelLB)
//TpeakHigh = (fastHMA > fastChannelUB) and (fastChannelLB > avg(slowChannelUB,slowChannelLB))
//TpeakLow = (fastHMA < fastChannelUB) and (fastChannelUB < avg(slowChannelLB,slowChannelUB))
//TpeakHigh = ((crossover(fastHMA,fastChannelUB)) and (fastChannelLB > slowChannelUB))
//TpeakLow = ((crossover(fastChannelLB,fastHMA)) and (fastChannelUB < slowChannelLB))
//TpeakHigh = (fastHMA > (fastChannelUB * (1 + (trendPower/800)))) and (fastChannelUB > (slowChannelUB * (1 + (trendPower/800))))
//TpeakLow = (fastHMA < (fastChannelUB * (1 - (trendPower/800)))) and (fastChannelLB < (slowChannelLB * (1 - (trendPower/800))))
//TpeakHigh = (fastHMA > (fastChannelUB * (1 + (trendPower/800)))) and (avg(fastChannelUB,fastChannelLB) > (slowChannelUB * (1 + (trendPower/800))))
//TpeakLow = (fastHMA < (fastChannelUB * (1 - (trendPower/800)))) and (avg(fastChannelLB,fastChannelUB) < (slowChannelLB * (1 - (trendPower/800))))
//plot(fastChannelUB * (1 + (trendPower/700)), color=#FF69B4)
// and for closing...
closeLong = (crossover(fastHMA,fastChannelUB) and (fastChannelLB > slowChannelUB))
closeShort = (crossover(fastChannelLB,fastHMA) and (fastChannelUB < slowChannelLB))
//closeLong = (crossover(fastHMA,fastChannelUB) and (fastChannelLB > slowChannelUB)) or (roc(price,altClosePeriod) > altCloseFactor)
//closeShort = (crossover(fastChannelLB,fastHMA) and (fastChannelUB < slowChannelLB)) or (roc(price,altClosePeriod) < (altCloseFactor) * -1)
//closeLong = (crossover(fastHMA,fastChannelUB) and (fastChannelLB > slowChannelUB)) or (((price - fastChannelUB) > (altCloseFactor * abs(((fastChannelUB - fastChannelLB)/2) - ((slowChannelUB - slowChannelLB)/2)))) and (fastChannelLB > slowChannelUB))
//closeShort = (crossover(fastChannelLB,fastHMA) and (fastChannelUB < slowChannelLB)) or (((fastChannelLB - price) > (altCloseFactor * abs(((fastChannelUB - fastChannelLB)/2) - ((slowChannelUB - slowChannelLB)/2)))) and (fastChannelUB < slowChannelLB))
//closeLong = crossover(fastHMA,fastChannelUB) and ((fastChannelLB[0] - fastChannelLB[1]) < (slowChannelUB[0] - slowChannelUB[1]))
//closeShort = crossover(fastChannelLB,fastHMA) and ((fastChannelUB[0] - fastChannelUB[1]) > (slowChannelLB[0] - slowChannelLB[1]))
//stop-loss
priceDev = stdev(price,trendLookback) * (1 + stopLossFlexibility/5)
stopLossMod = stopLoss * (1 + (priceDev/price))
//longStopPrice = strategy.position_avg_price * (1 - (stopLoss/100))
//shortStopPrice = strategy.position_avg_price * (1 + (stopLoss/100))
longStopPrice = strategy.position_avg_price * (1 - (stopLossMod/100))
shortStopPrice = strategy.position_avg_price * (1 + (stopLossMod/100))
// volume
volumeMA = ema(volume,volumeMAlength)
volumeDecrease = ((not volRestrict ) or (volumeMA[0] < ema(volumeMA[1] * (1 - (volumeVolatilityCutoff/100)),5)))
volumeCutoff = ema(volumeMA[1] * (1 - (volumeVolatilityCutoff/100)),5)
//plot(volumeMA)
//plot(volumeCutoff)
// detect volatility
//trendinessLookback = input ( 600, step = 10, minval = 0)
trendinessLookback = trendLookback
trendiness = (stdev(price,trendinessLookback)/price) * (1 - (Restrictiveness/100))
longtermTrend = ((price - price[longTrendLookback])/price)
//dynamicTrendDetected = (dynamicRestrict and (abs(trendiness * 100) < trendSensitivity))
dynamicTrendDetected = (longtrendimpt and (dynamicRestrict and (abs(trendiness * 100) < (trendSensitivity+(longtermTrend * longTrendImportance))))) or (not longtrendimpt and ((dynamicRestrict and (abs(trendiness * 100) < trendSensitivity))))
// adapt conservativeness to volatility
//consVal = sma(((stdev(price,conservativenessLookback))/price)*100,25)
consVal = sma(((stdev(price,conservativenessLookback))/price)*100,25)
cVnorm = sma(avg(consVal,3),60)
cVal = consVal - cVnorm
//conservativenessMod = conservativeness * (cVal * consAffectFactor)
conservativenessMod = conservativeness * (consVal * consAffectFactor)
//plot(consVal,linewidth=4)
//plot(cVnorm,color = #00FF00)
//plot(cVal,linewidth=2)
// ROC cutoff (for CLOSING)
//rocCloseLong = (ema(roc(price,ROClength),10) > ROCcutoff)
//rocCloseShort = (ema(roc(price,ROClength),10) < (ROCcutoff * -1))
ROCval = roc(price,ROClength)
ROCema = ema(ROCval,30)
ROCabs = abs(ROCema)
ROCallow = ROCabs < ROCcutoff
ROCallowLong = (ROCabs < ROCcutoff) or ((ROCabs >= ROCcutoff) and ((fastChannelLB < slowChannelLB) and (fastHMA < fastChannelLB)))
ROCallowShort = (ROCabs < ROCcutoff) or ((ROCabs >= ROCcutoff) and ((fastChannelUB > slowChannelUB) and (fastHMA > fastChannelUB)))
//plot(ROCallow)
// obv
evidence_obv = (correlation(price,obv[0],obvLookback))
obvAllow = evidence_obv > obvCorrThreshold
//if (not na(vrsi))
if trendRestrict or dynamicTrendDetected
//if (strategy.position_size == 0)
if not (strategy.position_size < 0)
if trendUp
//if cbear and schL and fchL and trendUp and goLong
if cbear and TpeakLow and volumeDecrease and ROCallow and goLong and obvAllow
//if cbear and peakLow and rocHigh and volumeDecrease and goLong
strategy.entry("Long", strategy.long, comment="Long")
if not (strategy.position_size > 0)
if trendDown
//if cbull and schU and fchU and trendDown and goShort
if cbull and TpeakHigh and volumeDecrease and ROCallow and goShort and obvAllow
//if cbull and peakHigh and rocLow and volumeDecrease and goShort
strategy.entry("Short", strategy.short, comment="Short")
else
//if (strategy.position_size == 0)
if not (strategy.position_size < 0)
//if cbear and peakLow and goLong
//if cbear and peakLow and volumeDecrease and ROCallow and goLong
if TpeakLow and goLong and obvAllow
strategy.entry("Long", strategy.long, comment="Long")
if not (strategy.position_size > 0)
//if cbull and peakHigh and goShort
//if cbull and peakHigh and volumeDecrease and ROCallow and goShort
if TpeakHigh and goShort and obvAllow
strategy.entry("Short", strategy.short, comment="Short")
if conservativeClose
//pkHigh = ((fastHMA > fastChannelUB) and (fastChannelUB > (slowChannelUB * (1 + conservativeness/1000))))
//pkLow = ((fastHMA < fastChannelLB) and (fastChannelLB < (slowChannelLB * (1 - conservativeness/1000))))
//pkHigh = ((fastHMA > fastChannelUB) and (fastChannelUB > (slowChannelUB * (1 + conservativenessMod/1000))))
//pkLow = ((fastHMA < fastChannelLB) and (fastChannelLB < (slowChannelLB * (1 - conservativenessMod/1000))))
pkHigh = ((fastHMA > fastChannelUB) and (fastChannelUB > (slowChannelUB * (1 + ((conservativenessMod/1000) * (1 - Restrictiveness/100))))))
pkLow = ((fastHMA < fastChannelLB) and (fastChannelLB < (slowChannelLB * (1 - ((conservativenessMod/1000) * (1 - Restrictiveness/100))))))
if (strategy.position_size > 0)
//if fastAboveUB
//if pkHigh and closeLong
if closeLong
strategy.close("Long", comment="closeLong")
if (strategy.position_size < 0)
//if fastBelowLB
//if pkLow and closeShort
if closeShort
strategy.close("Short", comment="closeShort")
else
if (strategy.position_size > 0)
//if fastAboveUB
if peakHigh
strategy.close("Long", comment="closeLong")
if (strategy.position_size < 0)
//if fastBelowLB
if peakLow
strategy.close("Short", comment="closeShort")
if (strategy.position_size > 0)
strategy.exit(id="Long", stop=longStopPrice, comment="stopLong")
if (strategy.position_size < 0)
strategy.exit(id="Short", stop=shortStopPrice, comment="stopShort")
//plot(strategy.equity, title="equity", color=color.red, linewidth=2, style=plot.style_areabr)