Estrategia de reversión media basada en el ATR

El autor:¿ Qué pasa?, Fecha: 2023-10-17 16:27:44
Las etiquetas:

img

Resumen general

Esta estrategia utiliza pruebas de hipótesis para determinar si ATR se desvía de su valor medio. Combinado con la predicción de la tendencia del precio, implementa una estrategia de reversión media basada en ATR. Una desviación significativa de ATR indica una potencial volatilidad anormal en el mercado. Si se predice que la tendencia del precio será alcista, se puede establecer una posición larga.

Estrategia lógica

  1. Prueba de hipótesis

    • Se realizará una prueba t de dos muestras entre el período de ATR rápido (atr_fast) y el período de ATR lento (atr_slow).

    • Si la estadística de ensayo excede el umbral (intervalo de confianza especificado por el factor_fiabilidad), se rechazará la hipótesis nula, es decir, se considerará que el ATR rápido se desvía significativamente del ATR lento.

  2. Pronóstico de la tendencia de precios

    • La media móvil de los rendimientos logarítmicos se calcula como la tasa de deriva esperada (drift).

    • Si la deriva está aumentando, la tendencia actual se considera alcista.

  3. Entrada y salida de pérdidas de parada

    • Si el valor de la transacción es inferior al valor de la transacción, el valor de la transacción es igual al valor de la transacción.

    • Ajuste continuamente el stop loss utilizando ATR. Posición de salida cuando el precio se rompe por debajo del stop loss.

Análisis de ventajas

  • El uso de pruebas de hipótesis para determinar la desviación ATR es más científico y adaptativo.

  • La combinación con la predicción de la tendencia de los precios evita operaciones erróneas basadas únicamente en la desviación ATR.

  • El ajuste del stop loss gestiona continuamente el riesgo a la baja.

Análisis de riesgos

  • Incapaz de detener las pérdidas cuando el precio se desploma.

  • Una predicción de tendencia incorrecta puede resultar en comprar en la parte superior.

  • La configuración incorrecta de los parámetros puede no incluir la entrada correcta o agregar operaciones innecesarias.

Sugerencias para optimizar

  • Considere la posibilidad de añadir otros indicadores para la confirmación multifactorial para evitar errores.

  • Prueba diferentes combinaciones de parámetros ATR para encontrar valores más estables.

  • Añadir criterios sobre la ruptura de los niveles clave de precios para evitar una ruptura falsa.

Conclusión

La lógica general de esta estrategia es clara. El uso de pruebas de hipótesis para detectar volatilidad anormal es razonable. Sin embargo, la desviación de ATR por sí sola es insuficiente para determinar la tendencia. Se necesitan más factores de confirmación para mejorar la precisión. Las reglas de stop loss son confiables pero ineficaces contra choques de estilo acantilado. Se pueden hacer mejoras futuras en áreas como criterios de entrada, selección de parámetros, optimización 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

Más.