Stratégie de retour à la moyenne basée sur l'ATR


Date de création: 2023-10-17 16:27:44 Dernière modification: 2023-10-17 16:27:44
Copier: 2 Nombre de clics: 890
1
Suivre
1617
Abonnés

Stratégie de retour à la moyenne basée sur l’ATR

Aperçu

Cette stratégie utilise une méthode de test hypothétique pour déterminer si l’ATR s’est écarté de la moyenne, combinée à une prévision de l’évolution des prix, pour réaliser une stratégie de négociation de retour à la moyenne basée sur l’ATR. Lorsque l’ATR s’écarte de manière significative, cela indique que le marché peut être en fluctuation anormale.

Principe de stratégie

  1. Tests hypothétiques

    • Les deux échantillons t sont testés. L’hypothèse zéro H0 est la moyenne des deux échantillons sans différence notable.

    • Si les statistiques de test sont supérieures au seuil (la plage de confiance indiquée par le paramètre reliability_factor), l’hypothèse initiale est rejetée, à savoir que l’ATR rapide s’est clairement écarté de l’ATR lent.

  2. Prévisions de la tendance des prix

    • Calculer la moyenne mobile du rendement logarithmique en tant que dérivation attendue (paramètre de la dérive).

    • Si le taux de dérive augmente, on peut considérer que c’est une tendance à la hausse.

  3. Entrée et sortie à perte

    • Il est préférable de faire une entrée supplémentaire lorsque les variations ATR sont importantes et que la tendance est positive.

    • L’ATR est ensuite utilisé pour ajuster continuellement la ligne de stop-loss. La ligne de stop-loss est retirée lorsque le prix est en dessous de la ligne de stop-loss.

Analyse des avantages

  • Les tests hypothétiques sont utilisés pour déterminer si l’ATR s’écarte de la science et si les paramètres sont adaptés.

  • En combinant les prévisions de tendances de prix, on évite de faire des transactions erronées en se basant uniquement sur l’écart de l’ATR.

  • La régularisation des arrêts de perte pour réduire le risque de pertes.

Analyse des risques

  • Les prix ont baissé de façon spectaculaire, et il n’y a pas de moyen de les arrêter.

  • Il y a une erreur dans le jugement de la tendance et il est possible d’acheter le point le plus élevé.

  • Si les paramètres sont mal configurés, vous risquez de manquer le bon moment de transaction ou d’ajouter des transactions inutiles.

Conseils d’optimisation

  • Il est possible d’envisager d’ajouter d’autres indicateurs à la vérification multifactorielle, afin d’éviter que des transactions erronées ne soient générées par un seul indicateur.

  • Il est possible de tester différentes combinaisons de paramètres ATR pour trouver des paramètres plus stables.

  • Augmenter le jugement sur la rupture des seuils critiques et éviter d’acheter de fausses ruptures.

Résumer

Cette stratégie est clairement décrite dans l’idée générale. Il est préférable d’utiliser des tests hypothétiques pour juger des fluctuations anormales. Cependant, l’écart d’ATR ne peut pas être entièrement déterminé par la tendance.

Code source de la stratégie
/*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