La idea central de esta estrategia es combinar el indicador Supertrend con el comercio de curvas de acciones. Cuando el indicador Supertrend genera una señal de compra o venta, no ejecutamos directamente el comercio. En su lugar, verificamos si la curva de acciones actual está por debajo de su promedio móvil. Abriremos posiciones solo cuando la curva de acciones esté por encima del promedio móvil. Cuando la curva de acciones esté por debajo del promedio móvil, pausaremos el comercio para la estrategia actual. Esto puede prevenir efectivamente la expansión de las pérdidas.
Esta estrategia consta principalmente de dos partes:
La fórmula de cálculo del indicador Supertrend es:
Bandas superiores = Precio de origen - ATR multiplicador * ATR Banda inferior = Precio de origen + multiplicador ATR * ATR
El indicador de Supertrend utiliza el ATR para establecer las bandas superior e inferior. Una ruptura por encima de la banda superior significa una señal de venta, mientras que una ruptura por debajo de la banda inferior significa una señal de compra.
La idea detrás de la negociación de curvas de renta variable es que tomamos el promedio móvil de la curva de renta variable de la estrategia. Cuando la curva de renta variable cae por debajo de su promedio móvil, hacemos una pausa en la negociación de la estrategia actual y esperamos a que la curva de renta variable rebote por encima del promedio móvil antes de volver a activar la negociación.
Esta estrategia combina las dos técnicas, de modo que después de que el indicador de Supertrend genere una señal de negociación, no entramos directamente en operaciones. En su lugar, verificamos si la curva de renta variable actual está por encima de su promedio móvil. Solo cuando se cumplan ambas condiciones abriremos posiciones. Esto puede mitigar eficazmente los riesgos inherentes al indicador de Supertrend y evitar pérdidas excesivas.
Las principales ventajas de esta estrategia son las siguientes:
El indicador de Supertrend no puede frenar las pérdidas de manera efectiva. El comercio de curvas de acciones compensa esta deficiencia.
Cuando el comercio se vuelve desfavorable, se detiene el comercio para evitar pérdidas excesivas.
Puede gestionar posiciones automáticamente sin intervención manual. La negociación se detiene automáticamente cuando la curva de acciones cae por debajo del promedio móvil, y se reanuda cuando la curva de acciones rebota por encima de ella.
También hay algunos riesgos con esta estrategia:
Si se establecen los parámetros incorrectos, la negociación de la curva de renta variable puede resultar ineficaz, por lo que es necesario seleccionar los períodos de media móvil adecuados.
Es posible que no pueda ajustar las posiciones rápidamente cuando la tendencia del mercado cambie, lo que puede dar lugar a ciertas pérdidas.
Puede perder buenas oportunidades comerciales mientras espera que la curva de acciones se recupere.
Las medidas de contramedida:
Optimice los parámetros y seleccione el mejor período de media móvil.
Incorporar otros indicadores para juzgar la tendencia y ajustar las posiciones en consecuencia.
Acortar la duración de las operaciones suspendidas para reducir la probabilidad de oportunidades perdidas.
Podemos optimizar la estrategia desde los siguientes aspectos:
Prueba diferentes combinaciones de parámetros para determinar el período y el multiplicador óptimos de ATR.
Pruebe otros tipos de promedios móviles, como promedio móvil exponencial, promedio móvil Hull, etc.
Añadir otros indicadores para determinar la tendencia del mercado y ajustar las posiciones cuando la tendencia cambie.
Optimice el período de promedio móvil para encontrar el mejor equilibrio.
Optimice las condiciones para pausar la negociación, como establecer un umbral de stop loss antes de la suspensión.
Esta estrategia combina hábilmente el indicador Supertrend con el trading de curvas de acciones, aprovechando las fortalezas de ambas técnicas. Los resultados de las pruebas muestran que en la mayoría de los casos, aplicar el trading de curvas de acciones en realidad disminuye la rentabilidad. Como tal, esta estrategia es más adecuada para los traders defensivos. Con la optimización de parámetros y lógica, puede convertirse en una estrategia de trading cuantitativa muy práctica.
/*backtest start: 2023-01-14 00:00:00 end: 2024-01-14 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 strategy('Supertrend & Equity curve with EMA', overlay=false, format=format.price, precision=2, initial_capital=100000) eqlen = input.int(25, "EQ EMA len", group = "New Equity Curve Settings") shEQandMA = input.bool(true, "Show Original Equity Curve and MA") shEQfilt = input.bool(true, "Show Filtered Equity Curve by MA") Periods = input(title='ATR Period', defval=10, group = "SuperTrend Settings") src = input(hl2, title='Source', group = "SuperTrend Settings") Multiplier = input.float(title='ATR Multiplier', step=0.1, defval=3.0, group = "SuperTrend Settings") changeATR = input(title='Change ATR Calculation Method ?', defval=true, group = "SuperTrend Settings") //SuperTrend Code atr2 = ta.sma(ta.tr, Periods) atr = changeATR ? ta.atr(Periods) : atr2 up = src - Multiplier * atr up1 = nz(up[1], up) up := close[1] > up1 ? math.max(up, up1) : up dn = src + Multiplier * atr dn1 = nz(dn[1], dn) dn := close[1] < dn1 ? math.min(dn, dn1) : dn trend = 1 trend := nz(trend[1], trend) trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend // Strategy main code buySignal = trend == 1 and trend[1] == -1 sellSignal = trend == -1 and trend[1] == 1 if buySignal strategy.entry('Long', strategy.long) if sellSignal strategy.entry('Short', strategy.short) //Equity Curve calcs eq = strategy.netprofit ch = ta.change(eq) neq = ch != 0 ? eq : na mova = ta.ema(neq,eqlen) // New Equity Curve var float neweq = 0 var int ttrades = 0 var int wintrades = 0 var int losetrades = 0 switch strategy.netprofit == strategy.netprofit[1] => na strategy.netprofit < mova and strategy.netprofit[1] > mova => neweq := neweq + ch strategy.netprofit < mova and strategy.netprofit[1] < mova => na strategy.netprofit > mova and strategy.netprofit[1] > mova => neweq := neweq + ch newch = ta.change(neweq) switch newch == 0 => na newch > 0 => wintrades := wintrades +1 ttrades := ttrades +1 newch < 0 => losetrades := losetrades +1 ttrades := ttrades +1 //plot(eq, linewidth = 2) //plot(mova, color=color.red) //plot(neweq, color= color.green, linewidth = 3) //Table var testTable = table.new(position = position.top_right, columns = 5, rows = 10, bgcolor = color.green, border_width = 1) table.cell(table_id = testTable, column = 0, row = 0, text = "Strategy: ", bgcolor=color.white) table.cell(table_id = testTable, column = 1, row = 0, text = "Original: ", bgcolor=color.white) table.cell(table_id = testTable, column = 2, row = 0, text = "Equity Curve EMA: ", bgcolor=color.white) table.cell(table_id = testTable, column = 0, row = 1, text = "Total Trades: ", bgcolor=color.white) table.cell(table_id = testTable, column = 0, row = 2, text = "Win Trades: ", bgcolor=color.white) table.cell(table_id = testTable, column = 0, row = 3, text = "Lose Trades: ", bgcolor=color.white) table.cell(table_id = testTable, column = 0, row = 4, text = "Win Rate: ", bgcolor=color.white) table.cell(table_id = testTable, column = 0, row = 5, text = "Net Profit: ", bgcolor=color.white) //Equity Curve EMA stat table.cell(table_id = testTable, column = 2, row = 1, text = str.tostring(ttrades), bgcolor=color.white) table.cell(table_id = testTable, column = 2, row = 2, text = str.tostring(wintrades), bgcolor=color.white) table.cell(table_id = testTable, column = 2, row = 3, text = str.tostring(losetrades), bgcolor=color.white) table.cell(table_id = testTable, column = 2, row = 4, text = str.tostring(math.round(100*wintrades/ttrades,2)), bgcolor=color.white) table.cell(table_id = testTable, column = 2, row = 5, text = str.tostring(math.round(neweq)), bgcolor=color.white) //Original Strategy stat // table.cell(table_id = testTable, column = 1, row = 1, text = str.tostring(strategy.closedtrades), bgcolor=color.white) // table.cell(table_id = testTable, column = 1, row = 2, text = str.tostring(strategy.wintrades), bgcolor=color.white) // table.cell(table_id = testTable, column = 1, row = 3, text = str.tostring(strategy.losstrades), bgcolor=color.white) // table.cell(table_id = testTable, column = 1, row = 4, text = str.tostring(math.round(100*strategy.wintrades/strategy.closedtrades,2)), bgcolor=color.white) // table.cell(table_id = testTable, column = 1, row = 5, text = str.tostring(math.round(strategy.netprofit)), bgcolor=color.white) //New Equity curve var newcurve = array.new_float(0) var int ida = 0 var bool printEQ = false if newch !=0 array.push(newcurve, neweq) if bar_index > last_bar_index - array.size(newcurve) - 1 - 20 and array.size(newcurve) > 20 printEQ := true else printEQ := false plot(printEQ and ida < strategy.closedtrades and shEQfilt ? array.get(newcurve, ida) : na, color=color.green, linewidth = 2) if printEQ ida := ida + 1 if ida >= array.size(newcurve) and printEQ ida := array.size(newcurve) -1 //Original Equity curve var newcurve2 = array.new_float(0) var int ida2 = 0 var bool printEQ2 = false if ch !=0 array.push(newcurve2, eq) if bar_index > last_bar_index - array.size(newcurve2) - 1 - 20 and array.size(newcurve2) > 20 printEQ2 := true else printEQ2 := false plot(printEQ2 and ida2 < strategy.closedtrades and shEQandMA ? array.get(newcurve2, ida2) : na, color=color.blue, linewidth = 2) if printEQ2 ida2 := ida2 + 1 if ida2 >= array.size(newcurve2) and printEQ2 ida2 := array.size(newcurve2) -1 //Moving Average Array var marray = array.new_float(0) if ch array.push(marray, mova) plot(printEQ2 and array.size(marray) > 40 and shEQandMA ? array.get(marray, ida2-1) : na, color=color.red, linewidth = 1) hline(0,"0 line", color=color.black, linestyle = hline.style_dotted) if (last_bar_index-1) and array.size(newcurve2) > 20 and array.size(newcurve) > 20 l = label.new(bar_index+2, array.get(newcurve2, array.size(newcurve2)-1), "Original Equity Curve", color=color.rgb(33, 149, 243, 85), textcolor = color.black, style = label.style_label_left) label.delete(l[1]) f = label.new(bar_index+2, array.get(newcurve, array.size(newcurve)-1), "Filtered Equity Curve", color=color.rgb(69, 238, 97, 85), textcolor = color.black, style = label.style_label_left) label.delete(f[1])