
Un sistema de seguimiento de tendencias dinámicas en varios niveles es una estrategia de mejora basada en las reglas de negociación de la tortuga. La estrategia utiliza señales de tendencia de varios períodos de tiempo, combinando paradas dinámicas y posicionamientos piramidales, para lograr el control de tendencias a medio y largo plazo. El sistema capta tendencias de diferentes velocidades mediante la configuración de dos ciclos de seguimiento de tendencias (L1 y L2) y utiliza indicadores ATR adaptados para ajustar dinámicamente las posiciones de entrada, posición y parada.
Identificación de tendencias: utiliza dos periodos de media móvil (L1 y L2) para identificar tendencias de diferentes velocidades. La L1 se utiliza para capturar tendencias más rápidas, y la L2 para capturar tendencias más lentas pero más fiables.
La señal de entrada: se produce cuando el precio supera el punto más alto de L1 o L2. Si la última operación de L1 fue rentable, se salta la siguiente señal de L1 hasta que aparezca la señal de L2.
Detención dinámica: utiliza un múltiplo de ATR (el 3 por defecto) como distancia de detención inicial, el punto de detención se elevará gradualmente a medida que aumenta el tiempo de tenencia.
Posicionamiento de la pirámide: durante la continuación de la tendencia, se realizan posiciones de hasta 5 veces cada vez que el precio sube 0,5 ATR.
Control de riesgos: El riesgo de cada transacción no excede el 2% del valor neto de la cuenta mediante el cálculo dinámico de la cantidad de la posición.
Mecanismo de salida: cerrar la posición cuando el precio cae por debajo de los mínimos del día 10 (L1) o los mínimos del día 20 (L2) o cuando se activa la línea de parada móvil.
Captura de tendencias a varios niveles: a través de dos ciclos L1 y L2, se pueden capturar tendencias rápidas y captar tendencias a largo plazo, lo que aumenta la adaptabilidad y la estabilidad de la estrategia.
Gestión dinámica del riesgo: el uso del ATR como indicador de volatilidad permite un ajuste dinámico de las posiciones de entrada, parada y alza de posición para adaptarse mejor a los cambios en el mercado.
La pirámide aumenta su posición gradualmente a medida que la tendencia continúa, controlando el riesgo y maximizando el potencial de ganancias.
Ajustes de parámetros flexibles: los múltiples parámetros ajustables permiten que las estrategias se adapten a diferentes mercados y estilos de negociación.
Ejecución automatizada: Las estrategias pueden ser ejecutadas de forma totalmente automatizada, con menos intervención humana y menos impacto emocional.
Riesgo de reversión de la tendencia: El rendimiento es excelente en un mercado de tendencia fuerte, pero en un mercado de agitación, el comercio frecuente puede causar pérdidas.
Puntos de deslizamiento y costos de transacción: Los altos costos de transacción pueden ser causados por la acumulación frecuente de pérdidas y los parados móviles.
Riesgo de optimización excesiva: los parámetros son numerosos y son susceptibles a una adaptación excesiva de los datos históricos.
Riesgo de gestión de fondos: si el capital inicial es pequeño, es posible que no se pueda ejecutar con eficacia varias adiciones de capital.
Riesgo de liquidez del mercado: en mercados con poca liquidez, puede ser difícil ejecutar operaciones a precios ideales.
Introducción de filtros de entorno de mercado: se puede agregar un indicador de intensidad de tendencia (como el ADX) para juzgar el entorno de mercado, reduciendo la frecuencia de negociación en mercados convulsos.
Optimización de la estrategia de alza: se puede considerar la posibilidad de ajustar dinámicamente el intervalo y la frecuencia de alza en función de la intensidad de la tendencia, en lugar de fijar un ATR de 0.5 y 5 veces.
Introducción de un mecanismo de stop-loss: en una tendencia a largo plazo, se puede establecer un stop-loss parcial para bloquear las ganancias, como la cancelación de la mitad de la posición cuando se alcanza una ganancia de 3 veces el ATR.
Análisis de correlación entre variedades: cuando se usa en combinación, se puede agregar un análisis de correlación entre variedades para optimizar la relación riesgo-beneficio en general.
Añadir filtro de volatilidad: Suspender las operaciones o ajustar los parámetros de riesgo para responder a mercados anormales en períodos de alta volatilidad.
Mecanismos de salida optimizados: se puede considerar el uso de indicadores de salida más flexibles, como el parabólico SAR o el Chandelier Exit.
El sistema de seguimiento de tendencias dinámicas en varios niveles es una estrategia integral que combina las reglas clásicas de la negociación de la playa con la tecnología de la cuantificación moderna. A través de métodos como la identificación de tendencias en varios niveles, la gestión de riesgos dinámicos y la subida de posiciones de la pirámide, la estrategia mejora la capacidad de captura de tendencias y el potencial de ganancias, al tiempo que mantiene la estabilidad. Aunque se enfrenta a desafíos en mercados convulsionados, la estrategia espera mantener un rendimiento estable en diferentes entornos de mercado mediante la optimización de parámetros y el control de riesgos razonables.
/*backtest
start: 2024-06-28 00:00:00
end: 2024-07-28 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
// This is a strategy based on the famous turtle system.
// https://www.tradingblox.com/originalturtles/originalturtlerules.htm
//
// In a nutshell, it a trend trading system where you are buying on strength, selling on weakness.
// positions should be entered when the price crosses over the 20-day high (L1 high) or 55-day high (L2 high).
// positions should be exited when the prices crosses below the 10-day low (L1 low) or 20-day low (L2 low)
// you can add positions at every unit (measured by multiple of n, where n=1 ATR)
// stops should be placed at 2*n below every position entered, when the stop is hit exit your entire position.
// positions should be entered everytime price crosses over L1 or L2, with one exception:
// if the last trade was an L1 trade and it was a winning trade, skip the next trade unless the price crosses
// over L2, if that is the case, you should take it.
// L1 and L2 levels are also configurable for high and lows.
// N multiple for stops and pyramid are also configurable
// To change this from a strategy to a study:
// 1) uncomment the next line and comment out the strategy line.
// 2) at the end of the file comment out the last 2 lines
// study(title="Turtle Study", overlay=true)
strategy(title='kTF-VNI', overlay=true, initial_capital=100000000, commission_type=strategy.commission.percent, commission_value=0.0, pyramiding=100, process_orders_on_close=true, calc_on_every_tick=true)
stopInput = input.float(3, 'Stop N', step=.05)
riskPercent = input.float(.01, 'Risk % of capital', step=.005)
pyramidInput = input.float(0.5, 'Pyramid N', step=.05)
maxUnits = input.int(5, 'Max Pyramid Units', step=1)
atrPeriod = input(20, 'ATR period')
l1LongInput = 10
l2LongInput = 20
l1LongExitInput = 20
l2LongExitInput = 40
l1LongInput := input.int(20, 'L1 Long', minval=2)
l2LongInput := input.int(60, 'L2 Long', minval=2)
l1LongExitInput := input.int(10, 'L1 Long Exit', minval=2)
l2LongExitInput := input.int(20, 'L2 Long Exit', minval=2)
FromYear = input.int(1970, 'From Year', minval=1900)
FromMonth = input.int(1, 'From Month', minval=1, maxval=12)
FromDay = input.int(1, 'From Day', minval=1, maxval=31)
ToYear = input.int(9999, 'To Year', minval=1900)
ToMonth = input.int(1, 'To Month', minval=1, maxval=12)
ToDay = input.int(1, 'To Day', minval=1, maxval=31)
FromDate = timestamp(FromYear, FromMonth, FromDay, 00, 00)
ToDate = timestamp(ToYear, ToMonth, ToDay, 23, 59)
TradeDateIsAllowed() =>
time >= FromDate and time <= ToDate
l1Long = ta.highest(l1LongInput)
l1LongExit = ta.lowest(l1LongExitInput)
l2Long = ta.highest(l2LongInput)
l2LongExit = ta.lowest(l2LongExitInput)
bool win = false // tracks if last trade was winning trade of losing trade.
float buyPrice = 0.0 // tracks the buy price of the last long position.
float nextBuyPrice = 0.0 // tracks the next buy price
float stopPrice = na // tracks the stop price
int totalBuys = 0 // tracks the total # of pyramid buys
bool inBuy = false // tracks if we are in a long position or not.
float l1LongPlot = ta.highest(l1LongInput) // tracks the L1 price to display
float l2LongPlot = ta.highest(l2LongInput) // tracks the L2 price to display
float n = ta.atr(atrPeriod) // tracks the n used to calculate stops and pyramid buys
string mode = 'L1' // tracks whether we are in a L1 position or L2 position.
bool fake = na // tracks if this is a fake trade, see comments below.
string longLevel = na // tracks where long positions, stops, pyramid buys occur.
float capitalLeft = strategy.initial_capital
var shares = 0
float fakeBuyPrice = 0.0
// by default use the last value from the previous bar.
buyPrice := buyPrice[1]
totalBuys := totalBuys[1]
nextBuyPrice := nextBuyPrice[1]
stopPrice := stopPrice[1]
win := win[1]
capitalLeft := capitalLeft[1]
inBuy := inBuy[1]
n := ta.atr(atrPeriod)
fakeBuyPrice := fakeBuyPrice[1]
// State to track if we are in a long positon or not.
if not inBuy[1] and (high > l1Long[1] or high > l2Long[1])
inBuy := true
inBuy
else
inBuy := inBuy[1] and low < stopPrice[1] ? false : inBuy
inBuy := inBuy[1] and mode[1] == 'L1' and low < l1LongExit[1] ? false : inBuy
inBuy := inBuy[1] and mode[1] == 'L2' and low < l2LongExit[1] ? false : inBuy
inBuy
// State to track if we are ia a fake trade. If the last trade was a winning, we need to skip the next trade.
// We still track it though as a fake trade (not counted against us). as the outcome determines if we can
// can take the next trade.
if not inBuy[1] and high > l1Long[1] and win[1]
fake := true
fakeBuyPrice := close
fakeBuyPrice
else
fake := fake[1]
fake
if fake[1] and inBuy[1] and not inBuy
fake := false
win := close >= fakeBuyPrice
win
fake := high > l2Long[1] ? false : fake
// Series representing the l1 and l2 levels. If we break out above the l1 or l2 level, we want the
// line to stay at the breakout level, not follow it up.
l1LongPlot := not inBuy[1] or inBuy[1] and mode == 'L1' and fake[1] ? l1Long[1] : l1LongPlot[1]
l2LongPlot := not inBuy[1] or inBuy[1] and mode == 'L1' and fake[1] ? l2Long[1] : l2LongPlot[1]
// Variable in the series is only set when it happens. Possible values is L1, L2, SR
// (stopped out with a loss), SG (exited with a gain), and 'P' for pyramid buy.
longLevel := not inBuy[1] and high > l1Long[1] ? 'L1' : na
longLevel := (not inBuy[1] or inBuy[1] and fake[1]) and high > l2Long[1] ? 'L2' : longLevel
// Either 'L1' or 'L2' depending on what breakout level we are in.
mode := longLevel == na ? mode[1] : longLevel
// Variables to track calculating nextBuyPrice for pyramiding.
if longLevel == 'L1' or longLevel == 'L2'
buyPrice := close
totalBuys := 1
stopPrice := close - stopInput * n
nextBuyPrice := close + pyramidInput * n
nextBuyPrice
// Marks if we hit our next buy price, if so mark it with a 'P'
longLevel := longLevel == na and inBuy[1] and high > nextBuyPrice and TradeDateIsAllowed() and totalBuys < maxUnits ? 'P' : longLevel
if longLevel == 'P'
buyPrice := close
totalBuys := totalBuys[1] + 1
stopPrice := close - stopInput * n
nextBuyPrice := close + pyramidInput * n
nextBuyPrice
// Tracks stops and exits, marking them with SG or SR
longLevel := longLevel == na and inBuy[1] and low < stopPrice and close >= strategy.position_avg_price ? 'SG' : longLevel
longLevel := longLevel == na and inBuy[1] and low < stopPrice and close < strategy.position_avg_price ? 'SR' : longLevel
longLevel := longLevel == na and mode[1] == 'L1' and inBuy[1] and low < l1LongExit[1] and close >= strategy.position_avg_price ? 'SG' : longLevel
longLevel := longLevel == na and mode[1] == 'L2' and inBuy[1] and low < l2LongExit[1] and close >= strategy.position_avg_price ? 'SG' : longLevel
longLevel := longLevel == na and mode[1] == 'L1' and inBuy[1] and low < l1LongExit[1] and close < strategy.position_avg_price ? 'SR' : longLevel
longLevel := longLevel == na and mode[1] == 'L2' and inBuy[1] and low < l2LongExit[1] and close < strategy.position_avg_price ? 'SR' : longLevel
// Tracks if the trade was a win or loss.
win := longLevel == 'SG' ? true : win
win := longLevel == 'SR' ? false : win
// Variables used to tell strategy when to enter/exit trade.
//plotarrow(fake ? 1 : 0, colordown=color.red, colorup=color.purple, transp=40) // down arrow for winning trade
enterLong = (longLevel == 'L1' or longLevel == 'L2' or longLevel == 'P') and not fake and TradeDateIsAllowed()
exitLong = (longLevel == 'SG' or longLevel == 'SR') and not fake and TradeDateIsAllowed()
p1 = plot(l1LongPlot, title='l1 long', linewidth=3, style=plot.style_stepline, color=color.new(color.green, 0))
p2 = plot(l1LongExit[1], title='l1 exit', linewidth=3, style=plot.style_stepline, color=color.new(color.red, 0))
p3 = plot(l2LongPlot, title='l2 long', linewidth=2, style=plot.style_stepline, color=color.new(color.green, 0))
p4 = plot(l2LongExit[1], title='l2 exit', linewidth=2, style=plot.style_stepline, color=color.new(color.red, 0))
color1 = color.new(color.black, 0)
color2 = color.new(color.black, 100)
col = inBuy ? color1 : color2
p5 = plot(stopPrice, title='stop', linewidth=2, style=plot.style_circles, join=true, color=color.new(color.black, 0))
p6 = plot(nextBuyPrice, title='next buy', linewidth=2, style=plot.style_circles, join=true, color=color.new(color.blue, 0))
fill(p1, p3, color=color.new(color.green, 90))
fill(p2, p4, color=color.new(color.red, 90))
risk = (strategy.initial_capital + strategy.netprofit) * riskPercent
shares := math.floor(risk / (stopInput * n))
capitalLeft := strategy.initial_capital + strategy.netprofit - strategy.position_size * strategy.position_avg_price
if shares * close > capitalLeft
shares := math.max(0, math.floor(capitalLeft / close))
shares
shares := math.max(0, shares)
plotshape(longLevel == 'L1' and not fake and strategy.position_size == 0 ? true : false, color=color.new(color.green, 40), style=shape.triangleup, text='L1 ') // up arrow for entering L1 trade
plotshape(not fake[1] and fake and longLevel == 'L1' and strategy.position_size == 0 ? true : false, color=color.new(color.gray, 40), style=shape.triangleup, text='L1') // up arrow for entering L1 trade
plotshape(longLevel == 'L2' and strategy.position_size == 0 ? true : false, color=color.new(color.green, 40), style=shape.triangleup, text='L2') // up arrow for entering L2 trade
plotshape((mode == 'L1' or mode == 'L2') and shares > 0 and enterLong and strategy.position_size > 0 ? true : false, color=color.new(color.green, 40), style=shape.triangleup, text='P')
plotarrow(strategy.position_size == 0 and longLevel == 'L1' and enterLong ? 1 : 0, colordown=color.new(color.black, 40), colorup=color.new(color.green, 40)) // up arrow for entering L1 trade
plotarrow(strategy.position_size == 0 and longLevel == 'L2' and enterLong ? 1 : 0, colordown=color.new(color.black, 40), colorup=color.new(color.green, 40)) // up arrow for entering L2 trade
plotarrow(strategy.position_size > 0 and longLevel == 'SR' and exitLong ? -1 : 0, colordown=color.new(color.red, 40), colorup=color.new(color.purple, 40)) // down arrow for losing trade
plotarrow(strategy.position_size > 0 and longLevel == 'SG' and exitLong ? -1 : 0, colordown=color.new(color.green, 40), colorup=color.new(color.purple, 40)) // down arrow for winning trade
plotshape(longLevel == na and inBuy[1] and not inBuy, color=color.new(color.gray, 40), style=shape.triangleup, text='Exit') // up arrow for entering L1 trade
plot(ta.atr(atrPeriod), title='ATR', color=color.new(#991515, 0))
plot(strategy.position_avg_price, title='Average Price', color=color.new(#991515, 0))
alertcondition(low < stopPrice, title='crosses under stop price', message='price crossed under stop price')
alertcondition(high > l1Long, title='crosses over L1 price', message='price crossed over L1 price')
alertcondition(high > l2Long, title='crosses over L2 price', message='price crossed over L2 price')
alertcondition(low < l1LongExit, title='crosses under L1 exit price', message='price crossed under L1 exit price')
alertcondition(low < l2LongExit, title='crosses under L2 exit price', message='price crossed under L2 exit price')
strategy.entry('long', strategy.long, qty=shares, comment='long', when=enterLong)
strategy.close('long', when=exitLong)
// simulate_amount = 100000
// simulate_risk = simulate_amount*0.005
// simulate_shares = floor(simulate_risk/(n*stopInput))
// plot(simulate_shares, "Shares", color=#991515, transp=0)
// if (enterLong)
// label.new(bar_index, high, text=tostring(simulate), style=label.style_none)