Modelo de reversión de ruptura basado en la estrategia Turtle Trader


Fecha de creación: 2024-01-29 16:48:00 Última modificación: 2024-01-29 16:48:00
Copiar: 0 Número de Visitas: 738
1
Seguir
1617
Seguidores

Modelo de reversión de ruptura basado en la estrategia Turtle Trader

Descripción general

La estrategia se basa en la famosa estrategia de los comerciantes de la tortuga de la playa, que ha sido probada durante años. Envía señales de posición larga y posición vacía, con un máximo de 5 órdenes de pirámide, lo que significa que la estrategia puede desencadenar hasta 5 órdenes en la misma dirección.

Cabe señalar que la estrategia combina dos sistemas que trabajan juntos (S1 y S2).

Principio de estrategia

El tamaño de la posición es muy importante para los operadores de criptomonedas para administrar adecuadamente el riesgo. La estrategia de ajuste de la posición se adapta a la volatilidad del mercado y a la cuenta de ganancias y pérdidas. Se basa en el ATR, también conocido como el rango real promedio.

El número de unidades compradas fue:

unit = (percentage_to_risk/100)*account/atr*syminfo.pointvalue

De acuerdo con sus preferencias de riesgo, puede aumentar el porcentaje de su cuenta, pero los operadores de Turtles lo hacen por defecto al 1%. Si usted negocia contratos, la unidad debe tomar un saldo por defecto.

También hay una regla adicional para reducir el riesgo cuando el valor en cuenta es inferior al capital inicial: en este caso, en la fórmula de unidades debe sustituirse por la siguiente fórmula:

account := (strategy.equity-strategy.openprofit)*(strategy.equity-strategy.openprofit)/strategy.initial_capital

Hay dos sistemas que trabajan juntos: Una ruptura es un nuevo alto o un nuevo bajo. Si es un nuevo alto, abrimos una posición de más, y por el contrario, si es un nuevo bajo, abrimos una posición de más.

Y añadimos una regla adicional: Esta regla adicional permite a los operadores participar en la tendencia principal si se salta la señal del Sistema 1. Si se salta la señal del Sistema 1 y la siguiente línea K es también una nueva ruptura de 20 días, S1 no emitirá la señal. Debemos esperar la señal de S2 o esperar que no se produzca una nueva ruptura de la línea K para reactivar S1.

Análisis de las ventajas

La estrategia de la playa nos permite agregar unidades adicionales a la posición cuando el movimiento del precio es favorable para nosotros. He configurado la estrategia para permitir agregar hasta 5 órdenes en la misma dirección. Por lo tanto, si el precio cambia de compra a compra, agregaremos unidades.

Se establece el primer pedido como el orden máximo. Los pedidos posteriores de la pirámide tendrán menos unidades que el primer pedido.

Hemos establecido un máximo de stop loss del 10% para la primera orden, lo que significa que no perderás más del 10% del valor de la primera orden. Sin embargo, el stop loss aumentará/disminuirá en 0.5*ATR ((20), sus pedidos de pirámide pueden perder más, no hay garantía de que la pérdida no exceda el 10% . El riesgo sigue siendo muy bien administrado, ya que estos pedidos tienen un valor inferior al valor de la primera orden .

Análisis de riesgos

El mayor riesgo de esta estrategia es el exceso de posicionamiento. Debido a que los pedidos delegados se utilizan en el mercado, si se obtienen varios pedidos de gran valor al mismo tiempo, habrá un gran impacto en las ofertas, lo que provocará un gran deslizamiento. Esto puede causar una gran pérdida de capital.

El otro riesgo es la mala gestión de la asignación de fondos. La asignación errónea o excesiva de los estancamientos puede causar grandes pérdidas. Esto requiere una configuración cuidadosa de acuerdo con sus preferencias de riesgo.

Dirección de optimización

La estrategia puede ser optimizada en los siguientes aspectos:

  1. Se puede probar el impacto de diferentes parámetros en la rentabilidad y la tasa de Sharpe, como el ciclo ATR, el multiplicador ATR de la parada, etc. Encontrar la combinación óptima de parámetros.

  2. Se pueden probar diferentes reglas de entrada y salida, como el uso de la forma de la línea K como condición de filtrado adicional.

  3. Se pueden probar otros tipos de paradas, como paradas móviles, paradas dinámicas. Esto puede reducir la probabilidad de que el parador sea golpeado.

  4. Se pueden probar diferentes cantidades de pedidos de la pirámide. Cuanto más pedidos, mayor es el riesgo y la palanca. Encontrar el punto de equilibrio óptimo.

  5. Se puede intentar detener el comercio en un período de tiempo específico (por ejemplo, antes de que se publiquen los datos de empleo no agrícola en los Estados Unidos) para evitar el impacto de eventos importantes.

Resumir

En general, la estrategia tiene un buen equilibrio entre riesgos y ganancias, y es adecuada para el comercio de tendencias de línea media y larga. Tiene ventajas como la sistematización de la negociación y el control de los riesgos.

Código Fuente de la Estrategia
/*backtest
start: 2023-12-01 00:00:00
end: 2023-12-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gsanson66


//This strategy is based on the famous "Turtle Strategy"
//A well-known strategy which proved its performance during past years 
//@version=5
strategy("TURTLE STRATEGY", overlay=true)


//------------------------------TOOL TIPS--------------------------------//

t1 = "Percentage of the account the trader is willing to lose. This percentage is used to define the position size based on previous gains or losses. Turtle traders default to 1%."
t2 = "ATR Length"
t3 = "ATR Multiplier to fix the Stop Loss"
t4 = "Pyramiding : ATR Multiplier to set a profit target to increase position size"
t5 = "System 1 enter long if there is a new high after this selected period of time"
t6 = "System 2 enter long if there is a new high after this selected period of time"
t7 = "Exit Long from system 1 if there is a new low after this selected period of time"
t8 = "Exit Long from system 2 if there is a new low after this selected period of time"
t9 = "System 1 enter short if there is a new low after this selected period of time"
t10 = "System 2 enter short if there is a new low after this selected period of time"
t11 = "Exit short from system 1 if there is a new high after this selected period of time"
t12 = "Exit short from system 2 if there is a new high after this selected period of time"


//----------------------------------------FUNCTIONS---------------------------------------//

//@function Displays text passed to `txt` when called.
debugLabel(txt, color) =>
    label.new(bar_index, high, text=txt, color=color, style=label.style_label_lower_right, textcolor=color.black, size=size.small)

//@function which looks if the close date of the current bar falls inside the date range
inBacktestPeriod(start, end) => true


//---------------------------------------USER INPUTS--------------------------------------//

//Risk Management and turtle system input
percentage_to_risk = input.float(1, "Risk % of capital", maxval=100, minval=0, group="Turtle Parameters", tooltip=t1) 
atr_period = input.int(20, "ATR period", minval=1, group="Turtle Parameters", tooltip=t2)
stop_N_multiplier = input.float(1.5, "Stop ATR", minval=0.1, group="Turtle Parameters", tooltip=t3)
pyramid_profit = input.float(0.5, "Pyramid Profit", minval=0.01, group="Turtle Parameters", tooltip=t4)
S1_long = input.int(20, "S1 Long", minval=1, group="Turtle Parameters", tooltip=t5)
S2_long = input.int(55, "S2 Long", minval=1, group="Turtle Parameters", tooltip=t6)
S1_long_exit = input.int(10, "S1 Long Exit", minval=1, group="Turtle Parameters", tooltip=t7)
S2_long_exit = input.int(20, "S2 Long Exit", minval=1, group="Turtle Parameters", tooltip=t8)
S1_short = input.int(15, "S1 Short", minval=1, group="Turtle Parameters", tooltip=t9)
S2_short = input.int(55, "S2 Short", minval=1, group="Turtle Parameters", tooltip=t10)
S1_short_exit = input.int(7, "S1 Short Exit", minval=1, group="Turtle Parameters", tooltip=t11)
S2_short_exit = input.int(20, "S2 Short Exit", minval=1, group="Turtle Parameters", tooltip=t12)
//Backtesting period
startDate = input(title="Start Date", defval=timestamp("1 Jan 2020 00:00:00"), group="Backtesting Period")
endDate = input(title="End Date", defval=timestamp("1 July 2034 00:00:00"), group="Backtesting Period")


//----------------------------------VARIABLES INITIALISATION-----------------------------//

//Turtle variables
atr = ta.atr(atr_period)
var float buy_price_long = na
var float buy_price_short = na
var float stop_loss_long = na
var float stop_loss_short = na
float account = na
//Entry variables
day_high_syst1 = ta.highest(high, S1_long)
day_low_syst1 = ta.lowest(low, S1_short)
day_high_syst2 = ta.highest(high, S2_long)
day_low_syst2 = ta.lowest(low, S2_short)
var bool skip = false
var bool unskip_buffer_long = false
var bool unskip_buffer_short = false
//Exit variables
exit_long_syst1 = ta.lowest(low, S1_long_exit)
exit_short_syst1 = ta.highest(high, S1_short_exit)
exit_long_syst2 = ta.lowest(low, S2_long_exit)
exit_short_syst2 = ta.highest(high, S2_short_exit)
float exit_signal = na
//Backtesting period
bool inRange = na


//------------------------------CHECKING SOME CONDITIONS ON EACH SCRIPT EXECUTION-------------------------------//
strategy.initial_capital = 50000
//Checking if the date belong to the range
inRange := inBacktestPeriod(startDate, endDate)

//Checking if the current equity is higher or lower than the initial capital to adjusted position size
if strategy.equity - strategy.openprofit < strategy.initial_capital
    account := (strategy.equity-strategy.openprofit)*(strategy.equity-strategy.openprofit)/strategy.initial_capital
else
    account := strategy.equity - strategy.openprofit

//Checking if we close all trades in case where we exit the backtesting period
if strategy.position_size!=0 and not inRange
    strategy.close_all()
    debugLabel("END OF BACKTESTING PERIOD : we close the trade", color=color.rgb(116, 116, 116))


//--------------------------------------SKIP MANAGEMENT------------------------------------//
    
//Checking if a long signal has been skiped and system2 is not triggered
if skip and high>day_high_syst1[1] and high<day_high_syst2[1]
    unskip_buffer_long := true

//Checking if a short signal has been skiped and system2 is not triggered
if skip and low<day_low_syst1[1] and low>day_low_syst2[1]
    unskip_buffer_short := true

//Checking if current high is lower than previous 20_day_high after a skiped long signal to set skip to false
if unskip_buffer_long
    if high<day_high_syst1[1]
        skip := false
        unskip_buffer_long := false

//Checking if current low is higher than previous 20_day_low after a skiped short signal to set skip to false
if unskip_buffer_short
    if low>day_low_syst1[1]
        skip := false
        unskip_buffer_short := false

//Checking if we have an open position to reset skip and unskip buffers
if strategy.position_size!=0 and skip
    skip := false
    unskip_buffer_long := false
    unskip_buffer_short := false


//--------------------------------------------ENTRY CONDITIONS--------------------------------------------------//

//We calculate the position size based on turtle calculation
unit = (percentage_to_risk/100)*account/atr*syminfo.pointvalue

//Long order for system 1
if not skip and not (strategy.position_size>0) and inRange
    strategy.cancel("Long Syst 2")
    //We check that position size doesn't exceed available equity
    if unit*day_high_syst1>account
        unit := account/day_high_syst1
    stop_loss_long := day_high_syst1 - stop_N_multiplier*atr
    //We adjust SL if it's greater than 10% of trade value and fix it to 10%
    if stop_loss_long < day_high_syst1*0.9
        stop_loss_long := day_high_syst1*0.9
    strategy.order("Long Syst 1", strategy.long, unit, stop=day_high_syst1)
    buy_price_long := day_high_syst1

//Long order for system 2
if skip and not (strategy.position_size>0) and inRange
    //We check that position size doesn't exceed available equity
    if unit*day_high_syst2>account
        unit := account/day_high_syst2
    stop_loss_long := day_high_syst2 - stop_N_multiplier*atr
    //We adjust SL if it's greater than 10% of trade value and fix it to 10%
    if stop_loss_long < day_high_syst2*0.9
        stop_loss_long := day_high_syst2*0.9
    strategy.order("Long Syst 2", strategy.long, unit, stop=day_high_syst2)
    buy_price_long := day_high_syst2

//Short order for system 1
if not skip and not (strategy.position_size<0) and inRange
    strategy.cancel("Short Syst 2")
    //We check that position size doesn't exceed available equity
    if unit*day_low_syst1>account
        unit := account/day_low_syst1
    stop_loss_short := day_low_syst1 + stop_N_multiplier*atr
    //We adjust SL if it's greater than 10% of trade value and fix it to 10%
    if stop_loss_short > day_low_syst1*1.1
        stop_loss_short := day_low_syst1*1.1
    strategy.order("Short Syst 1", strategy.short, unit, stop=day_low_syst1)
    buy_price_short := day_low_syst1

//Short order for system 2
if skip and not (strategy.position_size<0) and inRange
    //We check that position size doesn't exceed available equity
    if unit*day_low_syst2>account
        unit := account/day_low_syst2
    stop_loss_short := day_low_syst2 + stop_N_multiplier*atr
    //We adjust SL if it's greater than 10% of trade value and fix it to 10%
    if stop_loss_short > day_low_syst2*1.1
        stop_loss_short := day_low_syst2*1.1
    strategy.order("Short Syst 2", strategy.short, unit, stop=day_low_syst2)
    buy_price_short := day_low_syst2


//-------------------------------PYRAMIDAL------------------------------------//

//Pyramid for long orders
if close > buy_price_long + (pyramid_profit*atr) and strategy.position_size>0
    //We calculate the remaining capital
    remaining_capital = account - strategy.position_size*strategy.position_avg_price*(1-0.0018)
    //We calculate units to add to the long position
    units_to_add = (percentage_to_risk/100)*remaining_capital/atr*syminfo.pointvalue
    if remaining_capital > units_to_add
        //We set the new Stop loss
        stop_loss_long := stop_loss_long + pyramid_profit*atr
        strategy.entry("Pyramid Long", strategy.long, units_to_add)
        buy_price_long := close

//Pyramid for short orders
if close < buy_price_short - (pyramid_profit*atr) and strategy.position_size<0
    //We calculate the remaining capital
    remaining_capital = account + strategy.position_size*strategy.position_avg_price*(1-0.0018)
    //We calculate units to add to the short position
    units_to_add = (percentage_to_risk/100)*remaining_capital/atr*syminfo.pointvalue
    if remaining_capital > units_to_add
        //We set the new Stop loss
        stop_loss_short := stop_loss_short - pyramid_profit*atr
        strategy.entry("Pyramid Short", strategy.short, units_to_add)
        buy_price_short := close


//----------------------------EXIT ORDERS-------------------------------//

//Checking if exit_long_syst1 is higher than stop_loss_long
if strategy.opentrades.entry_id(0)=="Long Syst 1"
    if exit_long_syst1[1] > stop_loss_long
        exit_signal := exit_long_syst1[1]
    else
        exit_signal := stop_loss_long

//Checking if exit_long_syst2 is higher than stop_loss_long
if strategy.opentrades.entry_id(0)=="Long Syst 2"
    if exit_long_syst2[1] > stop_loss_long
        exit_signal := exit_long_syst2[1]
    else
        exit_signal := stop_loss_long

//Checking if exit_short_syst1 is lower than stop_loss_short
if strategy.opentrades.entry_id(0)=="Short Syst 1"
    if exit_short_syst1[1] < stop_loss_short
        exit_signal := exit_short_syst1[1]
    else
        exit_signal := stop_loss_short

//Checking if exit_short_syst2 is lower than stop_loss_short
if strategy.opentrades.entry_id(0)=="Short Syst 2"
    if exit_short_syst2[1] < stop_loss_short
        exit_signal := exit_short_syst2[1]
    else
        exit_signal := stop_loss_short

//If the exit order is configured to close the position at a profit, we set 'skip' to true (we substract commission)
if strategy.position_size*exit_signal>strategy.position_size*strategy.position_avg_price*(1-0.0018)
    strategy.cancel("Long Syst 1")    
    strategy.cancel("Short Syst 1")
    skip := true
if strategy.position_size*exit_signal<=strategy.position_size*strategy.position_avg_price*(1-0.0018)
    skip := false

//We place stop exit orders
if strategy.position_size > 0
    strategy.exit("Exit Long", stop=exit_signal)

if strategy.position_size < 0
    strategy.exit("Exit Short", stop=exit_signal)


//------------------------------PLOTTING ELEMENTS-------------------------------//

plotchar(atr, "ATR", "", location.top, color.rgb(131, 5, 83))
//Plotting enter threshold
plot(day_high_syst1[1], "20 day high", color.rgb(118, 217, 159))
plot(day_high_syst2[1], "55 day high", color.rgb(4, 92, 53))
plot(day_low_syst1[1], "20 day low", color.rgb(234, 108, 108))
plot(day_low_syst2[1], "55 day low", color.rgb(149, 17, 17))
//Plotting Exit Signal
plot(exit_signal, "Exit Signal", color.blue, style=plot.style_circles)
//Plotting our position
exit_long_syst2_plot = plot(exit_long_syst2[1], color=na)
day_high_syst2_plot = plot(day_high_syst2[1], color=na)
exit_short_syst2_plot = plot(exit_short_syst2[1], color=na)
day_low_syst2_plot = plot(day_low_syst2[1], color=na)
fill(exit_long_syst2_plot, day_high_syst2_plot, color=strategy.position_size>0 ? color.new(color.lime, 90) : na)
fill(exit_short_syst2_plot, day_low_syst2_plot, color=strategy.position_size<0 ? color.new(color.red, 90) : na)