Stratégie de tendance ATR pour l'inversion moyenne

Auteur:ChaoZhang est là., Date: le 21 septembre 2023 à 11h02:06
Les étiquettes:

Résumé

Cette stratégie utilise les hauts et les bas de la volatilité des prix pour déterminer le moment des entrées et sorties de positions.

La logique de la stratégie

  1. Utilisez l'indicateur ATR pour mesurer la volatilité des prix. Calculez l'ATR sur les 20 dernières périodes et obtenez sa moyenne mobile et son écart type. Si la valeur actuelle de l'ATR dépasse la moyenne plus un écart type, la volatilité des prix est considérée comme élevée.

  2. Utilisez le taux de changement de prix logarithmique de premier ordre pour déterminer la tendance des prix. Calculez le taux de changement de prix logarithmique proche au cours des 20 dernières périodes, obtenez sa moyenne mobile. Si le taux de changement actuel dépasse la moyenne pendant 3 jours consécutifs et est positif, le prix est considéré comme en hausse.

  3. Lorsque la volatilité des prix est élevée et que le prix montre une tendance haussière, allez long. Lorsque le prix baisse et que l'arrêt de la perte est déclenché, position fermée. Le prix de l'arrêt de la perte est ajusté dynamiquement pour rester en dessous du prix le plus bas moins 2 fois ATR.

Analyse des avantages

  1. Utiliser la volatilité des prix et la tendance pour déterminer le temps long/courte, éviter le sur-échange sur les marchés variés.

  2. Le stop loss dynamique évite une perte excessive lors d'arrêts trop larges.

  3. Le backtest montre un rendement annualisé de 159% au cours de la période 2015-2021, ce qui dépasse de loin 120% du buy & hold.

Analyse des risques

  1. Les paramètres ATR trop agressifs peuvent entraîner trop peu d'opportunités d'entrée.

  2. L'indicateur de tendance peut générer de faux signaux qui contredisent la tendance réelle.

  3. Il faut un échantillon plus grand et une vérification de la robustesse pour éviter un surajustement.

  4. Impossible d'évaluer les performances dans des conditions extrêmes comme les flash crashs.

Directions d'optimisation

  1. Ajouter plus d'indicateurs de confirmation de tendance comme MACD, KDJ pour améliorer la précision de la tendance.

  2. Adapter les paramètres ATR en fonction des différents produits et régimes du marché afin d'optimiser l'indicateur de volatilité.

  3. Ajoutez la logique de la rupture et les facteurs d'accélération de tendance pour mesurer les ruptures.

  4. Testez différents types de stop loss comme le pourcentage, le stop de volatilité sur la performance.

  5. Évaluer sur des indicateurs tels que la fréquence des échanges, la stabilité de la courbe, le tirage maximal pour assurer la robustesse.

Résumé

Cette stratégie combine les avantages de l'évaluation de la volatilité et de la tendance pour déterminer les points d'inversion possibles à entrer sur la volatilité amplifiée, et utilise des arrêts dynamiques pour contrôler le risque. Le backtest montre un alpha décent généré. Mais l'échantillon de 6 ans est limité, les paramètres clés doivent être ajustés en fonction du marché et plus de facteurs de confirmation sont nécessaires pour réduire les faux signaux. Une vérification complète de la robustesse est également requise avant de l'appliquer au trading en direct.


/*backtest
start: 2022-09-14 00:00:00
end: 2023-09-20 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 (kevinhhl)

//@version=4
strategy("Mean Reversion (ATR) Strategy [KL]",overlay=true,pyramiding=1)
ENUM_LONG = "Long"

// Timeframe {
backtest_timeframe_start = input(defval = timestamp("01 Apr 2000 13:30 +0000"), title = "Backtest Start Time", type = input.time)
USE_ENDTIME = input(false,title="Define backtest end-time (If false, will test up to most recent candle)")
backtest_timeframe_end = input(defval = timestamp("01 May 2021 19:30 +0000"), title = "Backtest End Time (if checked above)", type = input.time)
within_timeframe = true
// }

// Trailing stop loss {
ATR_X2_TSL = atr(input(14,title="Length of ATR for trailing stop loss")) * input(2.0,title="ATR Multiplier for trailing stop loss",type=input.float)
TSL_source = low
var stop_loss_price = float(0)
TSL_line_color = color.green, TSL_transp = 100
if strategy.position_size == 0 or not within_timeframe
    TSL_line_color := color.black
    stop_loss_price := TSL_source - ATR_X2_TSL 
else if strategy.position_size > 0
    stop_loss_price := max(stop_loss_price, TSL_source - ATR_X2_TSL)
    TSL_transp := 0
plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp))
// }

// Variables for confirmations of entry {
_len_volat = input(20,title="Length of ATR to determine volatility")
_ATR_volat = atr(_len_volat)
_avg_atr = sma(_ATR_volat, _len_volat)
_std_volat = stdev(_ATR_volat,_len_volat)
signal_diverted_ATR = _ATR_volat > (_avg_atr + _std_volat) or _ATR_volat < (_avg_atr - _std_volat)

_len_drift = input(20,title="Length of Drift")//default set to const: _len_vol's default value
_prcntge_chng = log(close/close[1])
_drift = sma(_prcntge_chng, _len_drift) - pow(stdev(_prcntge_chng, _len_drift),2)*0.5
_chg_drift = _drift/_drift[1]-1
signal_uptrend = (_drift > _drift[1] and _drift > _drift[2]) or _drift > 0

entry_signal_all = signal_diverted_ATR and signal_uptrend
// }

alert_per_bar(msg)=>
    prefix = "[" + syminfo.root + "] "
    suffix = "(P=" + tostring(close) + "; atr=" + tostring(_ATR_volat) + ")"
    alert(tostring(prefix) + tostring(msg) + tostring(suffix), alert.freq_once_per_bar)

// MAIN {
if within_timeframe

    if strategy.position_size > 0 and strategy.position_size[1] > 0 and (stop_loss_price/stop_loss_price[1]-1) > 0.005
        alert_per_bar("TSL raised to " + tostring(stop_loss_price))

    // EXIT:
	if strategy.position_size > 0 and TSL_source <= stop_loss_price
	    exit_msg = close <= strategy.position_avg_price ? "stop loss" : "take profit"
        strategy.close(ENUM_LONG, comment=exit_msg)
    // ENTRY:
    else if entry_signal_all and (strategy.position_size == 0 or (strategy.position_size > 0 and close > stop_loss_price))
		entry_msg = strategy.position_size > 0 ? "adding" : "initial"
		strategy.entry(ENUM_LONG, strategy.long, comment=entry_msg)

if strategy.position_size == 0
    stop_loss_price := float(0)
// }


Plus de