Estrategia de tendencia a corto plazo basada en decisiones basadas en múltiples indicadores

El autor:¿ Qué pasa?, Fecha: 2023-10-25 15:31:30
Las etiquetas:

img

Resumen general

Esta estrategia incorpora tres indicadores técnicos en diferentes dimensiones, incluidos los niveles de soporte/resistencia, el sistema de promedios móviles e indicadores de osciladores, para determinar la dirección de la tendencia a corto plazo para una mayor tasa de ganancia.

Estrategia lógica

El código primero calcula los niveles de soporte / resistencia del precio, incluidos los puntos de pivote estándar y los niveles de retroceso de Fibonacci, y los traza en el gráfico.

Luego calcula el precio promedio ponderado por volumen (VWAP) y el precio promedio para las señales de cruz dorada y cruz de muerte.

Por último, calcula el oscilador RSI estocástico para señales de sobrecompra y sobreventa, que pertenece al indicador de sobrecompra y sobreventa.

Al combinar señales en estas tres dimensiones, si el soporte/resistencia, VWAP y el RSI estocástico dan señales de compra, se abrirá una posición larga.

Análisis de ventajas

La mayor ventaja de esta estrategia es la combinación de indicadores en diferentes dimensiones, lo que hace que el juicio sea más completo y preciso con una mayor tasa de ganancia. Primero los niveles de soporte / resistencia definen la tendencia principal. Luego VWAP determina la tendencia a mediano y largo plazo. Finalmente, el RSI estocástico juzga la condición de sobrecompra / sobreventa.

Además, la función de toma de ganancias ayuda a bloquear un cierto porcentaje de las ganancias, ayudando a la gestión de riesgos.

Análisis de riesgos

El principal riesgo de esta estrategia es su dependencia de señales simultáneas de todos los indicadores para la toma de decisiones. Si algunos indicadores emiten señales defectuosas, puede llevar a decisiones equivocadas. Por ejemplo, cuando el RSI estocástico muestra sobrecompra pero el VWAP y el soporte / resistencia aún indican alcista, puede perder la oportunidad de compra al no entrar.

Además, el ajuste inadecuado de los parámetros de los indicadores podría conducir a juicios erróneos de la señal que requieren backtesting iterativo para la optimización.

Además, los eventos de cisne negro en el mercado a corto plazo pueden invalidar las señales de los indicadores.

Oportunidades de mejora

La estrategia puede mejorarse aún más en los siguientes aspectos:

  1. Incorpore más señales de indicadores como el volumen para medir la fuerza de la tendencia para una mejor precisión.

  2. Añadir modelos de aprendizaje automático para entrenar en los indicadores multidimensionales y descubrir automáticamente las estrategias óptimas.

  3. Optimizar los parámetros basados en diferentes productos para el ajuste adaptativo.

  4. Introducir el stop loss y el dimensionamiento de las posiciones basados en el drawdown para controlar mejor los riesgos.

  5. Realizar la optimización de la cartera para encontrar productos de baja correlación para la diversidad.

Conclusión

En general, esta estrategia es muy adecuada para el comercio de tendencias a corto plazo. Al combinar señales a través de dimensiones, puede filtrar ruido significativo para una mayor tasa de ganancia. Pero aún existen riesgos de señales erróneas que se pueden mejorar mediante mejoras adicionales. Con la optimización continua, esta estrategia tiene el potencial de convertirse en un sistema eficiente y robusto a corto plazo.


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

// EmperorBTC's VWAP Indicator & Strategy
//              v2.1
// 
//      coded by Bogdan Vaida

// This indicator was created after EmperorBTC's conditions on Twitter. 
// Good timeframes for it: 30', 15', 5'
// To convert from strategy to study switch the commented lines in the beginning
// and at the end of the script and vice versa.

// What this indicator does is to check if:
// o Pivot Point was crossed
// o Stoch-RSI and VWAP were crossed in current or previous candle
// o Candle (or previous candle) close is in the trend direction
// If all these are true then it will go long or short based on direction.


// FUTURE IDEAS: 
//  - Volume Expansion
//  - Candle Stick patterns

//@version=4

// 🔥Uncomment the line below for the indicator and comment the strategy lines
// study(title="EmperorBTC's VWAP Indicator", shorttitle="EMP-VWAP", overlay=true)

// 🔥 Uncomment the line below for the strategy and comment the above line
strategy(title="EmperorBTC's VWAP Strategy", shorttitle="EMP-VWAP", overlay=true, pyramiding=1)

plotAveragePriceCrossedPivotPoint = input(false, title="Plot Close Price Crossing Pivot Points?", group="Pivot Points")
plotPivotPoints = input(false, title="Plot Pivot Points?", group="Pivot Points")
pivotPointsType = input(title="Pivot Points type", defval="Fibonacci", options=["Fibonacci", "Traditional"], group="Pivot Points")

pivotPointCircleWidth = input(2, title="Width of Pivot Point circles", minval=1, group="Pivot Points")

plotVWAP = input(true, title="Plot VWAP?", group="VWAP")
plotAvgPrice = input(true, title="Plot Average Price?", group="VWAP")
plotVWAPCrossPrice = input(false, title="Plot Price Crossing VWAP?", group="VWAP")
reso = input(title="Period", type=input.resolution, defval="D", group="VWAP")
cumulativePeriod = input(14, "VWAP Cumulative Period", group="VWAP")

plotStochRSICross = input(false, title="Plot StochRSI Cross?", group="StochRSI")
smoothK = input(3, "K", minval=1, group="StochRSI", inline="K&D")
smoothD = input(3, "D", minval=1, group="StochRSI", inline="K&D")
lengthRSI = input(14, "RSI Length", minval=1, group="Stochastic-RSI", inline="length")
lengthStoch = input(14, "Stochastic Length", minval=1, group="Stochastic-RSI", inline="length")
rsiSrc = input(close, title="RSI Source", group="Stochastic-RSI")

plotLong = input(true, title="Plot Long Opportunity?", group="Strategy only")
plotShort = input(true, title="Plot Short Opportunity?", group="Strategy only")
tradingDirection = input(title="Strategy trading Direction: ", defval="L&S", options=["L&S", "L", "S"], group="Strategy only")
takeProfit = input(1.0, title='Take Profit %', group="Strategy only") / 100
plotTP = input(true, title="Plot Take Profit?", group="Strategy only")
startDate = input(title="Start Date", type=input.integer,
     defval=1, minval=1, maxval=31, group="Backtesting range", inline="Start Date")
startMonth = input(title="Start Month", type=input.integer,
     defval=1, minval=1, maxval=12, group="Backtesting range", inline="Start Date")
startYear = input(title="Start Year", type=input.integer,
     defval=2017, minval=1800, maxval=2100, group="Backtesting range", inline="Start Date")
endDate = input(title="End Date", type=input.integer,
     defval=31, minval=1, maxval=31, group="Backtesting range", inline="End Date")
endMonth = input(title="End Month", type=input.integer,
     defval=12, minval=1, maxval=12, group="Backtesting range", inline="End Date")
endYear = input(title="End Year", type=input.integer,
     defval=2050, minval=1800, maxval=2100, group="Backtesting range", inline="End Date")


// PivotPoint code (PVTvX by DGT has some nice code on PP)
candleHigh  = security(syminfo.tickerid,"D", high[1], lookahead=barmerge.lookahead_on)
candleLow   = security(syminfo.tickerid,"D", low[1], lookahead=barmerge.lookahead_on)
candleClose = security(syminfo.tickerid,"D", close[1], lookahead=barmerge.lookahead_on)

pivotPoint = (candleHigh+candleLow+candleClose) / 3

float resistance1 = na
float resistance2 = na
float resistance3 = na
float support1 = na
float support2 = na
float support3 = na

if pivotPointsType == "Fibonacci"
    resistance1 := pivotPoint + 0.382 * (candleHigh - candleLow)
    resistance2 := pivotPoint + 0.618 * (candleHigh - candleLow)
    resistance3 := pivotPoint + (candleHigh - candleLow)
    support1 := pivotPoint - 0.382 * (candleHigh - candleLow)
    support2 := pivotPoint - 0.618 * (candleHigh - candleLow)
    support3 := pivotPoint - (candleHigh - candleLow)
else if pivotPointsType == "Traditional"
    resistance1 := 2 * pivotPoint - candleLow
    resistance2 := pivotPoint + (candleHigh - candleLow)
    resistance3 := candleHigh + 2 * (pivotPoint - candleLow) 
    support1 := 2 * pivotPoint - candleHigh
    support2 := pivotPoint - (candleHigh - candleLow)
    support3 := candleLow - 2 * (candleHigh - pivotPoint)

plot(series = plotPivotPoints ? support1 : na, color=#ff0000, title="S1", style = plot.style_circles, linewidth = pivotPointCircleWidth)
plot(series = plotPivotPoints ? support2 : na, color=#800000, title="S2", style = plot.style_circles, linewidth = pivotPointCircleWidth)
plot(series = plotPivotPoints ? support3 : na, color=#330000, title="S3", style = plot.style_circles, linewidth = pivotPointCircleWidth)
plot(series = plotPivotPoints ? pivotPoint : na, color=#FFA500, title="PP", style = plot.style_circles, linewidth = pivotPointCircleWidth)
plot(series = plotPivotPoints ? resistance1 : na, color=#00FF00, title="R1", style = plot.style_circles, linewidth = pivotPointCircleWidth)
plot(series = plotPivotPoints ? resistance2 : na, color=#008000, title="R2", style = plot.style_circles, linewidth = pivotPointCircleWidth)
plot(series = plotPivotPoints ? resistance3 : na, color=#003300, title="R3", style = plot.style_circles, linewidth = pivotPointCircleWidth)

pivotPointCrossedUp = ((low < support3) and (close > support3)) or ((low < support2) and (close > support2)) or ((low < support1) and (close > support1)) or  ((low < pivotPoint) and (close > pivotPoint))
pivotPointCrossedDown = ((high > support3) and (close < support3)) or ((high > support2) and (close < support2)) or ((high > support1) and (close < support1)) or  ((high > pivotPoint) and (close < pivotPoint))
plotPPColor = pivotPointCrossedUp ? color.green :
     pivotPointCrossedDown ? color.red :
     na

plotshape(series = plotAveragePriceCrossedPivotPoint ? (pivotPointCrossedUp or pivotPointCrossedDown) : na, title="PP Cross", style = shape.triangleup, location=location.belowbar, color=plotPPColor, text="PP", size=size.small)

// VWAP (taken from the TV code)
// There are five steps in calculating VWAP:
//
// 1. Calculate the Typical Price for the period. [(High + Low + Close)/3)]
// 2. Multiply the Typical Price by the period Volume (Typical Price x Volume)
// 3. Create a Cumulative Total of Typical Price. Cumulative(Typical Price x Volume)
// 4. Create a Cumulative Total of Volume. Cumulative(Volume)
// 5. Divide the Cumulative Totals. 
//
// VWAP = Cumulative(Typical Price x Volume) / Cumulative(Volume)

// Emperor's Edition
t = time(reso)
debut = na(t[1]) or t > t[1]

addsource = ohlc4 * volume
addvol = volume
addsource := debut ? addsource : addsource + addsource[1]
addvol := debut ? addvol : addvol + addvol[1]
vwapValue = addsource / addvol

pVWAP = plot(series = plotVWAP ? vwapValue : na, color=color.purple, title="VWAP")
pAvgPrice = plot(series = plotAvgPrice ? ohlc4 : na, color=color.blue, title="PRICE")
fill(pVWAP, pAvgPrice, color = ohlc4 > vwapValue ? color.red : color.green, title="VWAP PRICE FILL")

vwapCrossUp = (low < vwapValue) and (vwapValue < high) and (close > open) // added green candle check
vwapCrossDown = (high > vwapValue) and (vwapValue > low) and (close < open) // added red candle check

plotVWAPColor = vwapCrossUp ? color.green :
     vwapCrossDown ? color.red :
     na
plotshape(series = plotVWAPCrossPrice ? (vwapCrossUp or vwapCrossDown) : na, title="VWAP Cross Price", style=shape.triangleup, location=location.belowbar, color=plotVWAPColor, text="VWAP", size=size.small)


// Stochastic RSI

rsi1 = rsi(rsiSrc, lengthRSI)
k = sma(stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK)
d = sma(k, smoothD)

sRsiCrossUp = k[1] < d[1] and k > d
sRsiCrossDown = k[1] > d[1] and k < d

plotColor = sRsiCrossUp ? color.green :
     sRsiCrossDown ? color.red :
     na
plotshape(series = plotStochRSICross ? (sRsiCrossUp or sRsiCrossDown) : na, title="StochRSI Cross Up", style=shape.triangleup, location=location.belowbar, color=plotColor, text="StochRSI", size=size.small)

// Long Trades
sRsiCrossedUp = sRsiCrossUp or sRsiCrossUp[1]
vwapCrossedUp = vwapCrossUp or vwapCrossUp[1]
// longCond1 = (sRsiCross and vwapCross) or (sRsiCross[1] and vwapCross) or (sRsiCross and vwapCross[1])
longCond1 = (sRsiCrossedUp[1] and vwapCrossedUp[1])
longCond2 = pivotPointCrossedUp[1]
longCond3 = (close[1] > open[1]) and (close > open) // check this
longCond = longCond1 and longCond2 and longCond3
plotshape(series = plotLong ? longCond : na, title="Long", style=shape.triangleup, location=location.belowbar, color=color.green, text="Long", size=size.normal)

// Short Trades
sRsiCrossedDown = sRsiCrossDown or sRsiCrossDown[1]
vwapCrossedDown = vwapCrossDown or vwapCrossDown[1]
shortCond1 = (sRsiCrossedDown[1] and vwapCrossedDown[1])
shortCond2 = pivotPointCrossedDown[1]
shortCond3 = (close[1] < open[1]) and (close < open)
shortCond = shortCond1 and shortCond2 and shortCond3
plotshape(series = plotShort ? shortCond : na, title="Short", style=shape.triangledown, location=location.abovebar, color=color.red, text="Short", size=size.normal)

// alertcondition(condition=longCond, title="Long", message="Going long")
// alertcondition(condition=shortCond, title="Short", message="Going short")

// 🔥 Uncomment the lines below for the strategy and revert for the study
takeProfitLong     = strategy.position_avg_price * (1 + takeProfit)
takeProfitShort     = strategy.position_avg_price * (1 - takeProfit)
exitTp = ((strategy.position_size > 0) and (close > takeProfitLong)) or ((strategy.position_size < 0) and (close < takeProfitShort))
strategy.risk.allow_entry_in(tradingDirection == "L" ? strategy.direction.long : tradingDirection == "S" ? strategy.direction.short : strategy.direction.all)
plot(series = (plotTP and strategy.position_size > 0) ? takeProfitLong : na, title="TP Level",color=color.green, style=plot.style_linebr, linewidth=2)
plot(series = (plotTP and strategy.position_size < 0) ? takeProfitShort : na, title="TP Level",color=color.red, style=plot.style_linebr, linewidth=2)
inDateRange = (time >= timestamp(syminfo.timezone, startYear,
         startMonth, startDate, 0, 0)) and (time < timestamp(syminfo.timezone, endYear, endMonth, endDate, 0, 0))
strategy.entry("VWAP", strategy.long, comment="Long", when=longCond and inDateRange)
strategy.entry("VWAP", strategy.short, comment="Short", when=shortCond and inDateRange)
strategy.close(id="VWAP", when=exitTp)
if (not inDateRange)
    strategy.close_all()

Más.