Estrategia de promedio móvil de ruptura en espiral

El autor:¿ Qué pasa?, Fecha: 2024-01-15 11:45:23
Las etiquetas:

img

Resumen general

Esta estrategia combina el indicador del canal espiral y el indicador de la tasa de cambio (ROC). Genera señales de compra cuando el precio rompe la banda superior y la media móvil, y señales de venta cuando el precio rompe la banda inferior y la media móvil. El canal espiral determina la dirección de la tendencia mientras que el ROC detecta el impulso del precio. Al requerir el acuerdo entre ambos indicadores, la estrategia tiene como objetivo mejorar la confiabilidad de las señales comerciales y la tasa de ganancia.

Estrategia lógica

La estrategia se basa en dos indicadores clave:

  1. Canales en espiral: Traza las bandas superior e inferior para determinar la dirección de la tendencia.

  2. Tasa de cambio (ROC): Detecta la aceleración de los precios. ROC por encima de un umbral positivo sugiere una aceleración del movimiento al alza de los precios, mientras que ROC por debajo de un umbral negativo apunta a una aceleración del movimiento a la baja.

Las señales de compra se generan cuando tanto el canal espiral como ROC dan indicaciones alcistas, es decir, la ruptura del precio por encima de la banda superior junto con un impulso ascendente acelerado.

Las señales combinadas ayudan a evitar el comercio contra la tendencia y mejoran la fiabilidad.

Ventajas

  1. Señales confiables con mayor tasa de ganancia al requerir un acuerdo entre tendencia e impulso.

  2. Frecuencia de negociación personalizable mediante ajuste de parámetros, por ejemplo, ajuste de parámetros ROC.

  3. Stop loss para limitar el riesgo a la baja en operaciones individuales.

  4. Mecanismo de reingreso para manejar las tendencias y aumentar aún más la rentabilidad.

Los riesgos

  1. Perdiendo algunas oportunidades comerciales y limitando el potencial de ganancia debido al requisito de fiabilidad de la señal.

  2. Vulnerable a quedar atrapado cuando la tendencia se invierte, lo que podría llevar a grandes pérdidas.

  3. Un ajuste de parámetros deficiente puede dar lugar a muy pocas o demasiadas señales.

  4. Porcentaje de pérdida fijo no capaz de prevenir pérdidas graves en grandes fluctuaciones adversas de precios.

Oportunidades de mejora

  1. Optimice los parámetros de ROC para obtener el mejor rendimiento.

  2. Prueba diferentes niveles de stop loss para equilibrar el riesgo y la recompensa.

  3. Añadir otros filtros como el volumen, los indicadores de volatilidad para refinar las señales.

  4. Evaluar el rendimiento en diferentes mercados para encontrar el mejor ajuste.

  5. Introducir el dimensionamiento dinámico de las posiciones para diferentes condiciones de mercado.

Conclusión

La estrategia combina el canal espiral y el ROC para evaluar la dirección de la tendencia y el impulso. Su objetivo es la fiabilidad de la señal mientras se mantiene la rentabilidad a través de la reentrada y el ajuste de parámetros.


/*backtest
start: 2024-01-07 00:00:00
end: 2024-01-14 00:00:00
period: 45m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("SSL Chaikin BF 🚀", overlay=true, precision=2, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.075)

/////////////// Time Frame ///////////////
_0 = input(false,  "════════ Test Period ═══════")
testStartYear = input(2017, "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

/////////////// Chaikin MF /////////////// 
_1 = input(false,  "═══════ Chaikin MF ═══════")
length = input(20, minval=1, title = "Chaikin SMA Length")
upperThreshold = input(0.04, step=0.01, title="Upper Threshold")
lowerThreshold = input(0.02, step=0.01, title="Lower Threshold")
ad = close==high and close==low or high==low ? 0 : ((2*close-low-high)/(high-low))*volume
mf = sum(ad, length) / sum(volume, length)

/////////////// SSL Channels /////////////// 
_2 = input(false,  "═════════ SSL ══════════")
len1=input(title="SMA Length 1", defval=12)
len2=input(title="SMA Length 2", defval=13)

smaHigh = sma(high, len1)
smaLow = sma(low, len2)

Hlv = 0
Hlv := close > smaHigh ? 1 : close < smaLow ? -1 : Hlv[1]
sslDown = Hlv < 0 ? smaHigh : smaLow
sslUp = Hlv < 0 ? smaLow : smaHigh

///////////// Rate Of Change ///////////// 
_3 = input(false,  "══════ Rate of Change ══════")
source = close
roclength = input(13, "ROC Length",  minval=1)
pcntChange = input(4, "ROC % Change", 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 = sslUp > sslDown and isMoving() or crossover(mf, upperThreshold)
short = sslUp < sslDown and isMoving() or crossunder(mf, lowerThreshold)

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])

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

//////////////// Stop loss /////////////// 
_4 = input(false,  "════════ Stop Loss ═══════")
sl_inp = input(2.0, title='Stop Loss %') / 100

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("L", strategy.long, when=long)
    strategy.entry("S", strategy.short, when=short)
    strategy.exit("L SL", "L", stop=long_sl, when=since_longEntry > 0)
    strategy.exit("S SL", "S", stop=short_sl, when=since_shortEntry > 0)

/////////////// Plotting /////////////// 
p1 = plot(sslDown, linewidth = 1, color=color.red)
p2 = plot(sslUp, linewidth = 1, color=color.lime)
fill(p1, p2,  color = sslDown < sslUp ? color.lime : color.red, transp=80)
bgcolor(isMoving() ? long ? color.green : short ? color.red : na : color.white, transp=80)
bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=30)
bgcolor(crossover(mf, upperThreshold) ? color.blue : crossunder(mf, lowerThreshold) ? color.orange : na, transp=30)

Más.