Estrategia de inversión de seguimiento de doble canal

El autor:¿ Qué pasa?, Fecha: 2023-11-02 16:31:50
Las etiquetas:

img

Resumen general

La estrategia de inversión de seguimiento de doble canal es una estrategia de inversión de trading que combina bandas de Bollinger, canales de Keltner e indicadores de impulso.

Estrategia lógica

  1. Calcular las bandas medias, superiores e inferiores de las bandas de Bollinger

    • Banda media utiliza SMA de cerca
    • Las bandas superior e inferior son la banda media ± múltiple de desviación estándar ajustable
  2. Calcular las bandas media, superior e inferior para los canales de Keltner

    • Banda media utiliza SMA de cerca
    • Las bandas superior e inferior son la banda media ± múltiple de ATR ajustable
  3. Determine si las bandas de Bollinger están dentro de los canales de Keltner

    • Apretar cuando BB inferior > KC inferior y BB superior < KC superior
    • Si no, me quito.
  4. Calcular la inclinación de regresión lineal val de cerrar contra los puntos medios BB y KC

    • val > 0 indica que el cierre está aumentando, val < 0 significa que disminuye
  5. Calcular el ROC y la EMA de ROC para el cierre

    • Determinar si la tasa de cambio excede el umbral ajustable
    • Por encima del umbral indica la tendencia existente
  6. Cuando se comprime, largo cuando val > 0 y ROC excede el umbral

    • Y viceversa para abreviar.
  7. Establecer las condiciones de stop loss y take profit

Ventajas

  1. Mejora de la precisión mediante la combinación del sistema de doble canal para la inversión

  2. Evite señales falsas utilizando regresión lineal y velocidad de cambio

  3. Parámetros ajustables flexibles para la optimización entre productos

  4. Control efectivo del riesgo por operación con stop loss/take profit

  5. Datos suficientes de pruebas previas para validar la viabilidad de la estrategia

Riesgos y soluciones

  1. Presionar no siempre conduce a una reversión efectiva

    • Optimización de los parámetros y ajuste de los criterios de compresión
  2. Las fugas falsas generan señales equivocadas.

    • Añadir regresión lineal para determinar la dirección de la tendencia
  3. Pérdida de parada demasiado amplia que conduce a una pérdida única excesiva

    • Optimizar los puntos de stop loss y el control por pérdida de operaciones
  4. Periodos de prueba insuficientes

    • Ampliar las pruebas en más períodos para demostrar la viabilidad a largo plazo

Oportunidades de mejora

  1. Optimización de parámetros para más productos

  2. Añadir aprendizaje automático para la identificación de soporte/resistencia

  3. Incorporar el cambio de volumen para mejorar la validez de la ruptura

  4. Ejecutar análisis de marcos de tiempo múltiples para determinar la persistencia de la tendencia

  5. Optimizar el stop loss/take profit dinámico

Conclusión

La estrategia de reversión de seguimiento de doble canal utiliza indicadores como bandas de Bollinger y canales de Keltner para la negociación de reversión. Con la optimización de parámetros, se puede adaptar a diferentes productos para identificar la validez de la ruptura hasta cierto punto.


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

//@version=4
// Credit for the initial Squeeze Momentum code to LazyBear, rate of change code is from Kiasaki
strategy("Squeeze X BF 🚀", overlay=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.0)

/////////////// Time Frame ///////////////
testStartYear = input(2012, "Backtest Start Year") 
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay, 0, 0)

testStopYear = input(2019, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay, 0, 0)

testPeriod() => true

/////////////// Squeeeeze ///////////////
length = input(20, title="BB Length")
mult = input(2.0,title="BB MultFactor")
lengthKC=input(22, title="KC Length")
multKC = input(1.5, title="KC MultFactor")
 
useTrueRange = input(true, title="Use TrueRange (KC)")
 
// Calculate BB
source = close
basis = sma(source, length)
dev = mult * stdev(source, length)
upperBB = basis + dev
lowerBB = basis - dev

// Calculate KC
ma = sma(source, lengthKC)
range = useTrueRange ? tr : (high - low)
rangema = sma(range, lengthKC)
upperKC = ma + rangema * multKC
lowerKC = ma - rangema * multKC

sqzOn  = (lowerBB > lowerKC) and (upperBB < upperKC)
sqzOff = (lowerBB < lowerKC) and (upperBB > upperKC)
noSqz  = (sqzOn == false) and (sqzOff == false)

val = linreg(source - avg(avg(highest(high, lengthKC), lowest(low, lengthKC)),sma(close,lengthKC)), lengthKC,0)

///////////// Rate Of Change ///////////// 
roclength = input(30, minval=1), pcntChange = input(7, minval=1)
roc = 100 * (source - source[roclength]) / source[roclength]
emaroc = ema(roc, roclength / 2)
isMoving() => emaroc > (pcntChange / 2) or emaroc < (0 - (pcntChange / 2))

/////////////// Strategy ///////////////
long = val > 0 and isMoving()
short = val < 0 and isMoving()

last_long = 0.0
last_short = 0.0
last_long := long ? time : nz(last_long[1])
last_short := short ? time : nz(last_short[1])

long_signal = crossover(last_long, last_short)
short_signal = crossover(last_short, last_long)

last_open_long_signal = 0.0
last_open_short_signal = 0.0
last_open_long_signal := long_signal ? open : nz(last_open_long_signal[1])
last_open_short_signal := short_signal ? open : nz(last_open_short_signal[1])

last_long_signal = 0.0
last_short_signal = 0.0
last_long_signal := long_signal ? time : nz(last_long_signal[1])
last_short_signal := short_signal ? time : nz(last_short_signal[1])

in_long_signal = last_long_signal > last_short_signal
in_short_signal = last_short_signal > last_long_signal

last_high = 0.0
last_low = 0.0
last_high := not in_long_signal ? na : in_long_signal and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_short_signal ? na : in_short_signal and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])

sl_inp = input(100.0, title='Stop Loss %') / 100
tp_inp = input(5000.0, title='Take Profit %') / 100
 
take_level_l = strategy.position_avg_price * (1 + tp_inp)
take_level_s = strategy.position_avg_price * (1 - tp_inp)

since_longEntry = barssince(last_open_long_signal != last_open_long_signal[1]) 
since_shortEntry = barssince(last_open_short_signal != last_open_short_signal[1]) 

slLong = in_long_signal ? strategy.position_avg_price * (1 - sl_inp) : na
slShort = strategy.position_avg_price * (1 + sl_inp)
long_sl = in_long_signal ? slLong : na
short_sl = in_short_signal ? slShort : na

/////////////// Execution ///////////////
if testPeriod()
    strategy.entry("Long",  strategy.long, when=long)
    strategy.entry("Short", strategy.short, when=short)
    strategy.exit("Long Ex", "Long", stop=long_sl, limit=take_level_l, when=since_longEntry > 0)
    strategy.exit("Short Ex", "Short", stop=short_sl, limit=take_level_s, when=since_shortEntry > 0)
    
/////////////// Plotting ///////////////
bcolor = iff(val > 0, iff(val > nz(val[1]), color.lime, color.green), iff(val < nz(val[1]), color.red, color.maroon))
plot(val, color=bcolor, linewidth=4)
bgcolor(not isMoving() ? color.white : long ? color.lime : short ? color.red : na, transp=70)
bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=50)
hline(0, color = color.white)

Más.