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.
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.
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.
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.
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.
A perda de parada dinâmica evita perdas excessivas de paradas demasiado largas.
O backtest mostra um retorno anual de 159% durante 2015-2021, muito superior a 120% do buy & hold.
Parâmetros ATR excessivamente agressivos podem resultar em poucas oportunidades de entrada.
O indicador de tendência pode gerar falsos sinais contraditórios à tendência real.
O período de ensaio é de apenas 6 anos, precisamos de uma amostra maior e de uma verificação de robustez para evitar sobreajustes.
Incapaz de avaliar o desempenho em condições extremas como falhas de flash.
Adicionar mais indicadores de confirmação de tendência como MACD, KDJ para melhorar a precisão da tendência.
Ajustar os parâmetros do ATR de forma adaptativa com base em diferentes produtos e regimes de mercado para otimizar o indicador de volatilidade.
Adicione a lógica da fuga e os fatores de aceleração da tendência para avaliar as fugas.
Teste diferentes tipos de stop loss como percentagem, volatilidade stop no desempenho.
Avaliar em métricas como a frequência do comércio, a estabilidade da curva, a retirada máxima para garantir a robustez.
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) // }