
Esta estratégia utiliza métodos de testes de hipóteses para determinar se o ATR está desviado da média, combinando com a previsão de movimentos de preços, para implementar uma estratégia de negociação de retorno à média baseada no ATR. Quando o ATR se desvia significativamente, indica que o mercado pode estar em uma flutuação anormal.
Teste de hipóteses
Teste de duas amostras: a rápida ATR (parameteratr_fast) e a lenta ATR (parameteratr_slow). A hipótese de teste é a hipótese zero H0 para a média das duas amostras sem diferenças significativas.
Se a estatística de teste for superior ao limiar (o intervalo de confiança definido pelo parâmetro reliability_factor), a hipótese original é rejeitada, ou seja, o ATR rápido é considerado claramente desviado do ATR lento.
Previsão de evolução dos preços
Calcule a média móvel da taxa de retorno logarítmica como a taxa de deriva esperada (drift de parâmetros).
Se a taxa de deslocamento aumenta, então a tendência é pessimista.
Entradas e saídas com perdas
Quando a diferença de ATR é significativa e a tendência é positiva, faça mais entradas.
O ATR é usado para ajustar continuamente a linha de stop loss. A linha de stop loss é retirada quando o preço cai abaixo da linha de stop loss.
O uso de testes de hipóteses para determinar o ATR é um desvio anormal da ciência e os parâmetros são auto-adaptáveis.
A combinação com a previsão de tendências de preços evita que as transações erradas sejam feitas apenas com o desvio do ATR.
Ajuste contínuo do stop loss para reduzir o risco de perdas.
O preço do petróleo está em alta, mas os preços estão em baixa.
A tendência é de que haja um erro no julgamento da tendência e que se possa comprar o ponto mais alto.
Se os parâmetros não forem ajustados corretamente, você pode perder o momento correto de transação ou adicionar transações desnecessárias.
Pode-se considerar a adição de outros indicadores para a confirmação de múltiplos fatores, evitando que um único indicador cause transações erradas.
É possível testar diferentes combinações de parâmetros ATR para encontrar um parâmetro mais estável.
Aumentar o julgamento sobre a quebra de uma barreira de preços-chave, evitando a compra de falsas quebras.
A estratégia geral é clara, o uso de testes de hipótese para julgar oscilações anormais é desejável. No entanto, o desvio do ATR não pode julgar completamente a tendência, é necessário aumentar a base de julgamento para melhorar a precisão. A regra de parada de perda é confiável, mas não pode lidar com a queda de precipício. O futuro pode ser melhorado em termos de condições de entrada, seleção de parâmetros e otimização de parada de perda.
/*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