Estratégia de tendência ATR de reversão média

Autora:ChaoZhang, Data: 2023-09-21 11:42:06
Tags:

Resumo

Esta estratégia utiliza os altos e baixos da volatilidade dos preços para determinar o momento das entradas e saídas de posições.

Estratégia lógica

  1. Use o indicador ATR para medir a volatilidade dos preços. Calcule o ATR nos últimos 20 períodos e obtenha sua média móvel e desvio padrão. Se o valor atual do ATR exceder a média mais um desvio padrão, a volatilidade dos preços é considerada alta.

  2. Use a taxa de mudança de preço logarítmica de primeira ordem para determinar a tendência de preços. Calcule a taxa de mudança de preço logarítmica próxima nos últimos 20 períodos, obtenha sua média móvel. Se a taxa de mudança atual exceder a média por 3 dias consecutivos e for positiva, o preço é considerado em uma tendência de alta.

  3. Quando a volatilidade do preço é alta e o preço mostra uma tendência de alta, vá longo. Quando o preço retira e a perda de parada é acionada, a posição de fechamento. O preço de perda de parada é ajustado dinamicamente para permanecer abaixo do preço mais baixo menos 2 vezes ATR.

Análise das vantagens

  1. Utilizar a volatilidade e a tendência dos preços para determinar o tempo longo/curto, evitar o excesso de negociação em mercados variados.

  2. A perda de parada dinâmica evita perdas excessivas de paradas demasiado largas.

  3. O backtest mostra um retorno anual de 159% durante 2015-2021, muito superior a 120% do buy & hold.

Análise de riscos

  1. Parâmetros ATR excessivamente agressivos podem resultar em poucas oportunidades de entrada.

  2. O indicador de tendência pode gerar falsos sinais contraditórios à tendência real.

  3. O período de ensaio é de apenas 6 anos, precisamos de uma amostra maior e de uma verificação de robustez para evitar sobreajustes.

  4. Incapaz de avaliar o desempenho em condições extremas como falhas de flash.

Orientações de otimização

  1. Adicionar mais indicadores de confirmação de tendência como MACD, KDJ para melhorar a precisão da tendência.

  2. Ajustar os parâmetros do ATR de forma adaptativa com base em diferentes produtos e regimes de mercado para otimizar o indicador de volatilidade.

  3. Adicione a lógica da fuga e os fatores de aceleração da tendência para avaliar as fugas.

  4. Teste diferentes tipos de stop loss como percentagem, volatilidade stop no desempenho.

  5. Avaliar em métricas como a frequência do comércio, a estabilidade da curva, a retirada máxima para garantir a robustez.

Resumo

Esta estratégia combina as vantagens de medir a volatilidade e a tendência para determinar possíveis pontos de reversão para entrar na volatilidade amplificada, e usa paradas dinâmicas para controlar o risco. O backtest mostra alfa decente gerada. Mas a amostra de 6 anos é limitada, os parâmetros-chave precisam de ajuste específico do mercado e mais fatores de confirmação são necessários para reduzir os falsos sinais.


/*backtest
start: 2022-09-14 00:00:00
end: 2023-09-20 00:00:00
period: 1d
basePeriod: 1h
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/
// © DojiEmoji (kevinhhl)

//@version=4
strategy("Mean Reversion (ATR) Strategy [KL]",overlay=true,pyramiding=1)
ENUM_LONG = "Long"

// Timeframe {
backtest_timeframe_start = input(defval = timestamp("01 Apr 2000 13:30 +0000"), title = "Backtest Start Time", type = input.time)
USE_ENDTIME = input(false,title="Define backtest end-time (If false, will test up to most recent candle)")
backtest_timeframe_end = input(defval = timestamp("01 May 2021 19:30 +0000"), title = "Backtest End Time (if checked above)", type = input.time)
within_timeframe = true
// }

// Trailing stop loss {
ATR_X2_TSL = atr(input(14,title="Length of ATR for trailing stop loss")) * input(2.0,title="ATR Multiplier for trailing stop loss",type=input.float)
TSL_source = low
var stop_loss_price = float(0)
TSL_line_color = color.green, TSL_transp = 100
if strategy.position_size == 0 or not within_timeframe
    TSL_line_color := color.black
    stop_loss_price := TSL_source - ATR_X2_TSL 
else if strategy.position_size > 0
    stop_loss_price := max(stop_loss_price, TSL_source - ATR_X2_TSL)
    TSL_transp := 0
plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp))
// }

// Variables for confirmations of entry {
_len_volat = input(20,title="Length of ATR to determine volatility")
_ATR_volat = atr(_len_volat)
_avg_atr = sma(_ATR_volat, _len_volat)
_std_volat = stdev(_ATR_volat,_len_volat)
signal_diverted_ATR = _ATR_volat > (_avg_atr + _std_volat) or _ATR_volat < (_avg_atr - _std_volat)

_len_drift = input(20,title="Length of Drift")//default set to const: _len_vol's default value
_prcntge_chng = log(close/close[1])
_drift = sma(_prcntge_chng, _len_drift) - pow(stdev(_prcntge_chng, _len_drift),2)*0.5
_chg_drift = _drift/_drift[1]-1
signal_uptrend = (_drift > _drift[1] and _drift > _drift[2]) or _drift > 0

entry_signal_all = signal_diverted_ATR and signal_uptrend
// }

alert_per_bar(msg)=>
    prefix = "[" + syminfo.root + "] "
    suffix = "(P=" + tostring(close) + "; atr=" + tostring(_ATR_volat) + ")"
    alert(tostring(prefix) + tostring(msg) + tostring(suffix), alert.freq_once_per_bar)

// MAIN {
if within_timeframe

    if strategy.position_size > 0 and strategy.position_size[1] > 0 and (stop_loss_price/stop_loss_price[1]-1) > 0.005
        alert_per_bar("TSL raised to " + tostring(stop_loss_price))

    // EXIT:
	if strategy.position_size > 0 and TSL_source <= stop_loss_price
	    exit_msg = close <= strategy.position_avg_price ? "stop loss" : "take profit"
        strategy.close(ENUM_LONG, comment=exit_msg)
    // ENTRY:
    else if entry_signal_all and (strategy.position_size == 0 or (strategy.position_size > 0 and close > stop_loss_price))
		entry_msg = strategy.position_size > 0 ? "adding" : "initial"
		strategy.entry(ENUM_LONG, strategy.long, comment=entry_msg)

if strategy.position_size == 0
    stop_loss_price := float(0)
// }


Mais.