Stratégie d'inversion moyenne basée sur l'ATR

Auteur:ChaoZhang est là., Date: 2023-10-17 16:27:44 Je suis désolé
Les étiquettes:

img

Résumé

Cette stratégie utilise des tests d'hypothèses pour déterminer si l'ATR s'écarte de sa valeur moyenne. Combinée à la prédiction de la tendance des prix, elle implémente une stratégie de réversion moyenne basée sur l'ATR. Un écart significatif de l'ATR indique une volatilité anormale potentielle sur le marché. Si la tendance des prix est prédite haussière, une position longue peut être établie.

La logique de la stratégie

  1. Test des hypothèses

    • Effectuer un t-test sur deux échantillons entre la période d'ATR rapide (atr_fast) et la période d'ATR lente (atr_slow).

    • Si la statistique d'essai dépasse le seuil (intervalle de confiance spécifié par le facteur fiabilité), l'hypothèse nulle est rejetée, c'est-à-dire que l'ATR rapide est considéré comme déviant de manière significative de l'ATR lent.

  2. Prévision de l' évolution des prix

    • La moyenne mobile des rendements logarithmiques est calculée comme le taux de dérive attendu (drift).

    • Si la dérive augmente, la tendance actuelle est jugée haussière.

  3. Entrée et sortie de stop-loss

    • Le taux d'intérêt de l'indicateur de change est le plus élevé du marché.

    • Ajustez continuellement le stop loss à l'aide de l'ATR. Sortez de la position lorsque le prix dépasse le stop loss.

Analyse des avantages

  • L'utilisation de tests d'hypothèses pour déterminer l'écart ATR est plus scientifique et adaptative.

  • La combinaison avec la prédiction de l'évolution des prix évite les transactions erronées basées uniquement sur l'écart ATR.

  • L'ajustement continu du stop loss permet de gérer le risque à la baisse.

Analyse des risques

  • Incapable d'arrêter la perte quand le prix s'effondre.

  • Une prédiction de tendance incorrecte peut entraîner un achat en haut.

  • Des paramètres incorrects peuvent manquer la bonne entrée ou ajouter des transactions inutiles.

Suggestions d'optimisation

  • Considérez l'ajout d'autres indicateurs pour la confirmation multifactorielle afin d'éviter les erreurs.

  • Tester différentes combinaisons de paramètres ATR pour trouver des valeurs plus stables.

  • Ajouter des critères sur la percée des niveaux clés des prix pour éviter une fausse percée.

Conclusion

La logique générale de cette stratégie est claire. L'utilisation de tests d'hypothèses pour détecter une volatilité anormale est raisonnable. Cependant, l'écart ATR seul est insuffisant pour déterminer la tendance. Plus de facteurs de confirmation sont nécessaires pour améliorer la précision. Les règles de stop loss sont fiables mais inefficaces contre les crashs de style falaise. Des améliorations futures peuvent être apportées dans des domaines tels que les critères d'entrée, la sélection de paramètres, l'optimisation du 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

Plus de