Esta estratégia usa testes de hipóteses para determinar se a ATR desvia do seu valor médio. Combinada com a previsão da tendência de preços, implementa uma estratégia de reversão média baseada na ATR. Desvio significativo da ATR indica potencial volatilidade anormal no mercado.
Teste de hipóteses
Realizar um teste t de duas amostras entre o período ATR rápido (atr_fast) e o período ATR lento (atr_slow).
Se a estatística do ensaio exceder o limiar (intervalo de confiança especificado pelo fator de fiabilidade), rejeitar a hipótese nula, ou seja, considerar-se que o ATR rápido se desvia significativamente do ATR lento.
Previsão da tendência dos preços
A média móvel dos retornos logarítmicos é calculada como taxa de deriva esperada (drift).
Se a deriva estiver aumentando, a tendência atual é julgada como otimista.
Entrada e saída de perdas de paragem
O preço de venda é o preço de venda do produto.
Ajustar continuamente o stop loss usando o ATR. Sair da posição quando o preço for abaixo do stop loss.
Usar testes de hipóteses para determinar o desvio ATR é mais científico e adaptativo.
A combinação com a previsão da tendência dos preços evita operações erradas baseadas unicamente no desvio ATR.
O ajustamento do stop loss gerencia continuamente o risco de queda.
Incapaz de parar as perdas quando o preço cai.
A previsão incorreta da tendência pode resultar na compra no topo.
A configuração incorreta dos parâmetros pode deixar de inserir a entrada correta ou adicionar transações desnecessárias.
Considerar a adição de outros indicadores para confirmação multifatorial para evitar erros.
Teste diferentes combinações de parâmetros ATR para encontrar valores mais estáveis.
Adicionar critérios de ruptura dos níveis-chave de preços para evitar uma falsa ruptura.
A lógica geral desta estratégia é clara. Usar testes de hipótese para detectar volatilidade anormal é razoável. No entanto, o desvio ATR sozinho é insuficiente para determinar a tendência. São necessários mais fatores de confirmação para melhorar a precisão. As regras de stop loss são confiáveis, mas ineficazes contra acidentes de estilo penhasco. Melhorias futuras podem ser feitas em áreas como critérios de entrada, seleção de parâmetros, otimização de stop loss.
/*backtest start: 2022-10-16 00:00:00 end: 2023-10-16 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 //@version=5 strategy("Mean Reversion (ATR) Strategy v2 [KL] ", overlay=true, pyramiding=1) var string ENUM_LONG = "Long" var string GROUP_TEST = "Hypothesis testing" var string GROUP_TSL = "Stop loss" var string GROUP_TREND = "Trend prediction" backtest_timeframe_start = input(defval=timestamp("01 Apr 2000 13:30 +0000"), title="Backtest Start Time") within_timeframe = true // TSL: calculate the stop loss price. { ATR_TSL = ta.atr(input(14, title="Length of ATR for trailing stop loss", group=GROUP_TSL)) * input(2.0, title="ATR Multiplier for trailing stop loss", group=GROUP_TSL) TSL_source = low TSL_line_color = color.green TSL_transp = 100 var stop_loss_price = float(0) if strategy.position_size == 0 or not within_timeframe TSL_line_color := color.black stop_loss_price := TSL_source - ATR_TSL else if strategy.position_size > 0 stop_loss_price := math.max(stop_loss_price, TSL_source - ATR_TSL) TSL_transp := 0 plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp)) // } end of "TSL" block // Entry variables { // ATR diversion test via Hypothesis testing (2-tailed): // H0 : atr_fast equals atr_slow // Ha : reject H0 if z_stat is above critical value, say reliability factor of 1.96 for a 95% confidence interval len_fast = input(14,title="Length of ATR (fast) for diversion test", group=GROUP_TEST) atr_fast = ta.atr(len_fast) std_error = ta.stdev(ta.tr, len_fast) / math.pow(len_fast, 0.5) // Standard Error (SE) = std / sq root(sample size) atr_slow = ta.atr(input(28,title="Length of ATR (slow) for diversion test", group=GROUP_TEST)) test_stat = (atr_fast - atr_slow) / std_error reject_H0 = math.abs(test_stat) > input.float(1.645,title="Reliability factor", tooltip="Strategy uses 2-tailed test; Confidence Interval = Point Estimate (avg ATR) +/- Reliability Factor x Standard Error; i.e use 1.645 for a 90% confidence interval", group=GROUP_TEST) // main entry signal, subject to confirmation(s), gets passed onto the next bar var _signal_diverted_ATR = false if not _signal_diverted_ATR _signal_diverted_ATR := reject_H0 // confirmation: trend prediction; based on expected lognormal returns _prcntge_chng = math.log(close / close[1]) // Expected return (drift) = average percentage change + half variance over the lookback period len_drift = input(14, title="Length of drift", group=GROUP_TREND) _drift = ta.sma(_prcntge_chng, len_drift) - math.pow(ta.stdev(_prcntge_chng, len_drift), 2) * 0.5 _signal_uptrend = _drift > _drift[1] entry_signal_all = _signal_diverted_ATR and _signal_uptrend // main signal + confirmations // } end of "Entry variables" block // MAIN { // Update the stop limit if strategy holds a position if strategy.position_size > 0 and ta.change(stop_loss_price) strategy.exit(ENUM_LONG, comment="sl", stop=stop_loss_price) // Entry if within_timeframe and entry_signal_all strategy.entry(ENUM_LONG, strategy.long, comment=strategy.position_size > 0 ? "adding" : "initial") // Alerts _atr = ta.atr(14) alert_helper(msg) => prefix = "[" + syminfo.root + "] " suffix = "(P=" + str.tostring(close, "#.##") + "; atr=" + str.tostring(_atr, "#.##") + ")" alert(str.tostring(prefix) + str.tostring(msg) + str.tostring(suffix), alert.freq_once_per_bar) if strategy.position_size > 0 and ta.change(strategy.position_size) if strategy.position_size > strategy.position_size[1] alert_helper("BUY") else if strategy.position_size < strategy.position_size[1] alert_helper("SELL") // Clean up - set the variables back to default values once no longer in use if strategy.position_size == 0 stop_loss_price := float(0) if ta.change(strategy.position_size) _signal_diverted_ATR := false // } end of MAIN block