Uma estratégia de negociação de ETF baseada no ATR e no breakout

Autora:ChaoZhang, Data: 23 de dezembro de 2023 - 26 de dezembro de 2023
Tags:

img

Resumo

Esta é uma estratégia de negociação algorítmica do ETF baseada no Average True Range (ATR) e no breakout do preço.

Estratégia lógica

A estratégia baseia-se principalmente nos seguintes princípios:

  1. Use os preços mais altos e mais baixos de um determinado período (por exemplo, 20 velas) para determinar a tendência e direção do preço.

  2. Usar o ATR para calcular dinamicamente o nível de stop loss. O stop loss é colocado a uma distância do valor ATR de um período ATR multiplicado por um coeficiente (por exemplo 2) do preço de entrada.

  3. Utilize o ATR para determinar o nível de lucro. O lucro é colocado a uma distância do valor ATR de um período ATR multiplicado por um coeficiente (por exemplo 1) do preço de entrada.

  4. Usar o multiplicador ATR para trail stop loss. Fechar posições com stop loss quando o preço atravessa o nível de stop loss do trailer em direção desfavorável.

A estratégia é simples e confiável, uma vez que considera tanto a direção da tendência dos preços para capturar os movimentos dos preços em tempo hábil, como define o stop loss e o take profit para a captação de lucros e o controle de riscos.

Análise das vantagens

As vantagens desta estratégia incluem:

  1. A lógica estratégica é simples e clara, fácil de compreender e implementar.

  2. A utilização do ATR para calcular os níveis de stop loss e take profit adaptativos ajuda a dimensionamento flexível das posições e ao controlo do risco.

  3. As estratégias de breakout são boas para capturar tendências de preços, levando a bons retornos.

  4. O stop loss do reboque pode fechar as posições em tempo hábil, evitando perdas excessivas.

  5. É adequado para produtos com tendências óbvias, como ETFs e ações.

Análise de riscos

Os riscos da estratégia incluem:

  1. Podem ocorrer mais sinais falsos e aberturas reversas durante a consolidação de preços.

  2. O ajustamento inadequado dos parâmetros pode conduzir à ausência de tendências de preços ou a um número excessivo de transações desnecessárias.

  3. Os valores extremos dos parâmetros podem resultar em stop loss e take profit demasiado agressivos ou demasiado conservadores, influenciando a rentabilidade da estratégia.

  4. Os riscos subjacentes aos ETFs, como os riscos de política e de prémios, também podem afetar o desempenho da estratégia.

Soluções correspondentes:

  1. Otimizar os parâmetros para reduzir os negócios desnecessários.
  2. Adicione mais fatores e filtros para confirmar sinais de negociação.
  3. Ajustar os parâmetros de forma adaptável aos diferentes mercados.
  4. Diversificar a dimensão das posições de investimento e controlo de um único ETF.

Orientações de otimização

A estratégia pode ser melhorada a partir dos seguintes aspectos:

  1. Adicione indicadores como média móvel para filtrar sinais falsos.

  2. Desenvolver um módulo de otimização de parâmetros adaptativo para ajustar automaticamente parâmetros para diferentes períodos e produtos.

  3. Adotar modelos de aprendizagem de máquina para prever os próximos preços mais altos e mais baixos da vela para determinar os sinais de ruptura.

  4. Considere o excesso de volume de negociação para evitar uma falha.

  5. Otimizar o dimensionamento das posições iniciais e as percentagens de atribuição de forma adaptável aos diferentes produtos e regimes de mercado.

Conclusão

A estratégia tem uma lógica clara e simples. Os mecanismos centrais de breakout e adaptação ATR stop loss / take profit podem controlar efetivamente os riscos e bloquear os lucros. Aumentar ainda mais os fatores de lucro e as capacidades de controle de risco através da otimização de parâmetros e integrando mais filtros pode torná-lo uma estratégia quantitativa rentável e otimizável.


/*backtest
start: 2023-12-18 00:00:00
end: 2023-12-21 03:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © FX_minds

//@version=4
strategy("ETF tradedr", overlay=true, pyramiding=100, default_qty_type=strategy.percent_of_equity, default_qty_value=100)

//------------------------------ get user input
lookback                   = input(title="HH LL lookback", type=input.integer, defval=20)
ATR_periode                = input(title="ATR period", type=input.integer, defval=14)
ATR_SL_multiplier          = input(title="ATR SL multiplier", type=input.float, defval=2)
ATR_TP_multiplier          = input(title="ATR TP multiplier", type=input.float, defval=1)
trailing_SL_ATR_multiplier = input(title="ATR trailing SL multiplier", type=input.float, defval=3.5)
lookback_trailing_SL       = input(title="trailing SL lookback", type=input.integer, defval=4)
max_sequel_trades          = input(title="max sequel trades", type=input.float, defval=1)
trade_long                 = input(title= "trade long ?", type=input.bool, defval=true)
trade_short                = input(title= "trade short ?", type=input.bool, defval=false)

//------------------------------ determine entry conditions
long_condition   = barstate.isconfirmed and crossover(high, highest(high, lookback)[1])
short_condition  = barstate.isconfirmed and crossunder(low, lowest(low, lookback)[1])


//------------------------------ count open long trades
count_open_longs = 0
count_open_longs := nz(count_open_longs[1])

if (long_condition) 
    count_open_longs := count_open_longs +1
    //label.new(bar_index, low, tostring(count_open_longs, "#"), xloc.bar_index, yloc.belowbar, color.green, label.style_none, color.green, size.large)

if (short_condition)
    count_open_longs := 0


//------------------------------ count open short trades
count_open_shorts = 0
count_open_shorts := nz(count_open_shorts[1])

if (short_condition)
    count_open_shorts := count_open_shorts +1
    //label.new(bar_index, low, tostring(count_open_shorts, "#"), xloc.bar_index, yloc.belowbar, color.red, label.style_none, color.red, size.large)

if (long_condition)
    count_open_shorts := 0


//------------------------------ calculate entryprice
entryprice_long = long_condition ? close : na
entryprice_short = short_condition ? close : na


//------------------------------ calculate SL & TP
SL_distance = atr(ATR_periode) * ATR_SL_multiplier
TP_distance  = atr(ATR_periode) * ATR_TP_multiplier
trailing_SL_distance = atr(ATR_periode) * trailing_SL_ATR_multiplier

SL_long = entryprice_long - SL_distance
SL_short = entryprice_short + SL_distance

trailing_SL_short = lowest(close, lookback_trailing_SL) + trailing_SL_distance
trailing_SL_long  = highest(close, lookback_trailing_SL) - trailing_SL_distance

trailing_SL_short_signal = crossover(high, trailing_SL_short[1])
trailing_SL_long_signal = crossunder(low, trailing_SL_long[1])


//------------------------------ plot entry price & SL  
plot(entryprice_long, style=plot.style_linebr, color=color.white)
plot(SL_long, style=plot.style_linebr, color=color.red)
plot(SL_short, style=plot.style_linebr, color=color.green)
plot(trailing_SL_short, style=plot.style_linebr, color=color.red)
plot(trailing_SL_long, style=plot.style_linebr, color=color.green)


//------------------------------ submit entry orders
if (long_condition) and (count_open_longs <= max_sequel_trades) and (trade_long == true)
    strategy.entry("Long" + tostring(count_open_longs, "#"), strategy.long)
    strategy.exit("SL Long"+ tostring(count_open_longs, "#"), 
     from_entry="Long" + tostring(count_open_longs, "#"), stop=SL_long)

if (short_condition) and (count_open_shorts <= max_sequel_trades) and (trade_short == true)
    strategy.entry("Short" + tostring(count_open_shorts, "#"), strategy.short)
    strategy.exit("SL Short" + tostring(count_open_shorts, "#"), 
     from_entry="Short" + tostring(count_open_shorts, "#"), stop=SL_short)
    

//------------------------------ submit exit conditions
if (trailing_SL_long_signal)
    strategy.close("Long" + tostring(count_open_longs, "#"))
    strategy.close("Long" + tostring(count_open_longs-1, "#"))
    strategy.close("Long" + tostring(count_open_longs-2, "#"))
    strategy.close("Long" + tostring(count_open_longs-4, "#"))
    strategy.close("Long" + tostring(count_open_longs-5, "#"))
    strategy.close("Long" + tostring(count_open_longs-6, "#"))
    strategy.close("Long" + tostring(count_open_longs-7, "#"))
    strategy.close("Long" + tostring(count_open_longs-8, "#"))
    strategy.close("Long" + tostring(count_open_longs-9, "#"))
    
if (trailing_SL_short_signal)
    strategy.close("Short" + tostring(count_open_shorts, "#"))
    strategy.close("Short" + tostring(count_open_shorts-1, "#"))
    strategy.close("Short" + tostring(count_open_shorts-2, "#"))
    strategy.close("Short" + tostring(count_open_shorts-3, "#"))
    strategy.close("Short" + tostring(count_open_shorts-4, "#"))
    strategy.close("Short" + tostring(count_open_shorts-5, "#"))
    strategy.close("Short" + tostring(count_open_shorts-6, "#"))
    strategy.close("Short" + tostring(count_open_shorts-7, "#"))
    strategy.close("Short" + tostring(count_open_shorts-8, "#"))
    strategy.close("Short" + tostring(count_open_shorts-9, "#"))



Mais.