Esta estrategia tiene como objetivo capturar fuertes tendencias en los mercados de criptomonedas mediante el uso de múltiples canales y promedios móviles para identificar señales de tendencia, y combina indicadores de volumen para filtrar falsas rupturas mientras detiene las pérdidas de manera adaptativa para obtener ganancias, lo que permite obtener ganancias en los mercados de tendencia.
La estrategia utiliza una combinación de canal rápido, canal lento y promedio móvil rápido para identificar tendencias. Los parámetros del canal rápido son más sensibles para capturar las fluctuaciones de precios a corto plazo; los parámetros del canal lento son más moderados para juzgar la tendencia principal; los parámetros del medio móvil rápido están en el medio, generando señales comerciales cuando rompe el canal.
Específicamente, primero calcula los rieles superiores e inferiores del canal rápido y la media móvil. Cuando el precio rompe el rieles superior, si el rieles inferior del canal lento también está por encima del promedio móvil, se genera una señal larga; a la inversa, cuando rompe el rieles inferior, verifica si el rieles superior del canal lento está por debajo del promedio móvil, generando una señal corta.
Además, detecta el patrón de la línea K, lo que requiere que múltiples líneas K se organicen en secuencia para filtrar las falsas rupturas; y calcula el indicador de tasa de cambio de precios para determinar si ha entrado en una consolidación para evitar oportunidades de reversión perdidas; e incorpora indicadores de volumen para garantizar que el volumen siga el precio en la ruptura.
Para el stop loss, la estrategia utiliza los stop loss adaptativos. Basado en la volatilidad reciente, ajusta dinámicamente el porcentaje de stop loss. Esto permite bloquear la mayor cantidad posible de la ganancia de la tendencia al tiempo que garantiza un stop loss efectivo.
La mayor ventaja de esta estrategia es que los criterios para generar señales comerciales son relativamente estrictos, lo que puede filtrar eficazmente las falsas rupturas no tendenciales y capturar verdaderamente los puntos de inflexión en las tendencias del mercado.
La combinación de múltiples canales y medias móviles tiene criterios más estrictos y puede reducir la probabilidad de error de juicio.
La validación de la secuencia de la línea K evita señales erróneas de una sola línea K aberrante.
La incorporación de un indicador de la tasa de cambio de precios puede determinar si ha entrado en consolidación para evitar oportunidades perdidas de reversión.
La adición del juicio del indicador de volumen asegura que las señales se generen solo cuando el volumen sigue al precio, evitando una ruptura ineficaz.
El mecanismo de stop loss adaptativo puede maximizar el bloqueo de las ganancias de tendencia al tiempo que garantiza el stop loss.
Así que en general, esta estrategia tiene las características de una configuración optimizada, toma de decisiones prudente, stop loss adaptativo, lo que la hace muy adecuada para capturar oportunidades de tendencia.
Aunque esta estrategia ha hecho una gran optimización en el filtrado de falsas rupturas y la captura de tendencias, todavía hay algunos riesgos a tener en cuenta:
La configuración compleja de parámetros puede dar lugar a grandes diferencias entre las combinaciones de parámetros, lo que requiere pruebas extensas para encontrar los parámetros óptimos, de lo contrario puede generar demasiadas señales falsas.
Cuando la brecha entre la media móvil rápida y el canal es demasiado pequeña, tiende a generar entradas y salidas frecuentes, lo que no favorece el seguimiento persistente de las tendencias.
El cálculo del porcentaje de stop loss en el mecanismo de stop loss adaptativo se basa en una simple desviación estándar, que puede dar lugar a un stop loss insuficiente en condiciones extremas de mercado.
Se basa en gran medida en indicadores técnicos y puede no responder a cambios fundamentales importantes.
Como tendencia que sigue la estrategia, su desempeño es inferior en los mercados agitados de rango.
Para controlar estos riesgos, se recomiendan las siguientes medidas:
Haga pruebas de retroceso suficientes para determinar las combinaciones óptimas de parámetros, o considere usar el aprendizaje automático para la optimización de parámetros.
Ampliar moderadamente los intervalos de canal, alargar los períodos de media móvil para reducir las entradas innecesarias.
Considere la introducción de modelos de volatilidad más avanzados como los métodos de fondos de cobertura.
Referirse a la información fundamental de manera oportuna para evitar el comercio puramente técnico.
Aumentar el juicio sobre los estados del mercado y detener las operaciones en mercados agitados.
La estrategia se puede optimizar aún más de las siguientes maneras:
Introducir algoritmos de aprendizaje automático para lograr la optimización automática de parámetros, registrando el rendimiento de los parámetros en diferentes entornos de mercado para construir una tabla de búsqueda para la optimización dinámica.
Añadir un juicio sobre los estados del mercado, como agregar módulos para determinar si el mercado está en tendencia o agitado, y pausar las operaciones en mercados agitados para evitar pérdidas innecesarias.
Optimizar las estrategias de stop loss, como las de stop loss de seguimiento, stop loss proporcional, etc.
Incorporar factores fundamentales para enviar alertas cuando se produzcan eventos fundamentales importantes, evitando pérdidas basadas únicamente en indicadores técnicos.
Realizar una optimización de la cartera, combinando esta estrategia con otras estrategias no relacionadas para diversificar aún más los riesgos.
Introducir un marco cuantitativo de negociación para la ejecución automatizada de señales y un estricto control de riesgos.
En resumen, esta estrategia es muy adecuada para capturar oportunidades de tendencia en los mercados de criptomonedas. Utiliza múltiples canales y promedios móviles para generar señales comerciales, y filtra efectivamente el ruido de ruptura falsa y bloquea con éxito las ganancias de tendencia. Pero la optimización de parámetros, los métodos de stop loss, el juicio del estado del mercado, etc. aún necesitan atención. Con una mejora continua, tiene potencial para retornos de inversión constantes. Proporciona un gran ejemplo para el diseño de estrategias cuantitativas.
/*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)