La stratégie de négociation d'inversion de la moyenne EMA ouvre et ferme des positions en fonction du degré de divergence du prix par rapport à la moyenne EMA. Elle utilise la différence en pourcentage entre le prix et la moyenne EMA comme signal d'entrée et de stop loss pour gérer les positions.
La stratégie utilise l'EMA comme référence et calcule la différence en pourcentage entre le prix actuel et l'EMA. Elle est longue lorsque le prix est suffisamment éloigné de l'EMA (défaut 9%), et ferme la position lorsque le prix se rapproche suffisamment de l'EMA (défaut 1%).
Plus précisément, la stratégie comprend les éléments suivants:
Calculer l'EMA. La période (par défaut 200), la source (prix de clôture) et la méthode (EMA, SMA, RMA, WMA) sont configurables.
Calculez la différence en pourcentage entre le prix actuel et l'EMA.
Les positions ouvertes sont basées sur le seuil de différence: l'entrée longue par défaut est de 9% et l'entrée courte de 9%.
Le nombre de marches et le pourcentage de pas par marche peuvent être configurés.
Utilisez le stop-loss de suivi après l'entrée. Le seuil pour commencer le suivi (revenu par défaut de 1%) et le pourcentage de suivi (par défaut de 1%) sont configurables.
La sortie par défaut est de 1% pour le long et le court.
Annuler les commandes non remplies lorsque le prix revient à l'EMA.
Pourcentage de stop loss configurable.
Prise en charge du backtesting et du trading en direct.
Les avantages de cette stratégie:
Utiliser le concept de réversion moyenne à la tendance du commerce basé sur l'écart EMA.
Les paramètres d'entrée, de stop loss et de sortie sont configurables pour s'adapter aux différentes conditions du marché.
L'entrée par échelle permet une accumulation progressive de position et réduit les coûts.
Le suivi des arrêts bloque les bénéfices et gère les risques.
Très optimisable en ajustant les paramètres EMA ou les seuils d'entrée/sortie.
Pine Script permet une utilisation simple dans TradingView.
Graphique intuitive pour l'observation et l'analyse.
Les risques de cette stratégie:
Risque de surajustement des paramètres des tests antérieurs: l'optimisation des paramètres peut surajuster les données des tests antérieurs et avoir un rendement inférieur dans le trading en direct.
Risque d'échec de l'EMA: le prix peut dévier de l'EMA pendant de longues périodes.
Le stop loss peut être pénétré par des mouvements volatils.
Une fréquence de négociation élevée entraîne des coûts de commission plus élevés.
Ils nécessitent une période de réflexion plus longue, plus susceptibles d'événements soudains.
Gestion des risques:
Sélection de paramètres robuste grâce à l'optimisation et à la vérification sur plusieurs marchés.
Une période raisonnable de mise à l'épreuve de l'EMA, ni trop courte ni trop longue.
Un tampon stop-loss plus large pour éviter d'être arrêté prématurément.
Des règles d'entrée moins agressives pour réduire la fréquence des échanges.
Incorporer des indicateurs supplémentaires tels que le volume, les bandes de Bollinger, le RSI pour s'adapter aux événements.
La stratégie peut être améliorée dans les domaines suivants:
Ajoutez des filtres comme le volume, les bandes de Bollinger, le RSI pour réduire les faux signaux.
Ajoutez une double EMA pour des transactions de tendance à probabilité plus élevée.
Améliorer le stop loss avec des stops adaptatifs, des sorties de chandelier pour limiter davantage le risque.
Ajoutez une optimisation automatique des paramètres pour trouver de meilleurs ensembles de paramètres.
Incorporer l'apprentissage automatique pour le risque de déviation EMA.
Considérez une position intraday ou overnight pour profiter des lacunes.
Intégrer la sélection de stock univers pour une plus grande capacité.
La stratégie de réversion moyenne de l'EMA est basée sur le comportement de réversion moyenne des prix autour d'une moyenne mobile. Elle utilise les propriétés statistiques de l'EMA de manière rationnelle pour identifier les changements de tendance et utilise le stop loss pour contrôler le risque.
/*backtest start: 2022-10-19 00:00:00 end: 2023-10-25 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/ // © jordanfray //@version=5 strategy(title="EMA Mean Reversion Strategy", overlay=true, max_bars_back=5000, default_qty_type=strategy.percent_of_equity, default_qty_value=100,initial_capital=100000, commission_type=strategy.commission.percent, commission_value=0.05, backtest_fill_limits_assumption=2) // Indenting Classs indent_1 = " " indent_2 = " " indent_3 = " " indent_4 = " " // Tooltips longEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, a long postion will open." shortEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, a short postion will open." closeEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, open postion will close." ladderInToolTip = "Enable this to use the laddering settings below." cancelEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, any unfilled entries will be canceled." // Group Titles group_one_title = "EMA Settings" group_two_title = "Entry Settings" // Colors blue = color.new(#00A5FF,0) lightBlue = color.new(#00A5FF,90) green = color.new(#2DBD85,0) gray_80 = color.new(#7F7F7F,80) gray_60 = color.new(#7F7F7F,60) gray_40 = color.new(#7F7F7F,40) white = color.new(#ffffff,0) red = color.new(#E02A4A,0) transparent = color.new(#000000,100) // Strategy Settings EMAtimeframe = input.timeframe(defval="", title="Timeframe", group=group_one_title) EMAlength = input.int(defval=200, minval=1, title="Length", group=group_one_title) EMAtype = input.string(defval="EMA", options = ["EMA", "SMA", "RMA", "WMA"], title="Type", group=group_one_title) EMAsource = input.source(defval=close, title="Source", group=group_one_title) openLongEntryAbove = input.float(defval=9, title="Long Position Entry Trigger", tooltip=longEntryToolTip, group=group_two_title) openEntryEntryAbove = input.float(defval=9, title="Short Position Entry Trigger", tooltip=shortEntryToolTip, group=group_two_title) closeEntryBelow = input.float(defval=1.0, title="Close Position Trigger", tooltip=closeEntryToolTip, group=group_two_title) cancelEntryBelow = input.float(defval=4, title="Cancel Unfilled Entries Trigger", tooltip=cancelEntryToolTip, group=group_two_title) enableLaddering = input.bool(defval=true, title="Ladder Into Positions", tooltip=ladderInToolTip, group=group_two_title) ladderRungs = input.int(defval=4, minval=2, maxval=4, step=1, title=indent_4+"Ladder Rungs", group=group_two_title) ladderStep = input.float(defval=.5, title=indent_4+"Ladder Step (%)", step=.1, group=group_two_title)/100 stop_loss_val = input.float(defval=4.0, title="Stop Loss (%)", step=0.1, group=group_two_title)/100 start_trailing_after = input.float(defval=1, title="Start Trailing After (%)", step=0.1, group=group_two_title)/100 trail_behind = input.float(defval=1, title="Trail Behind (%)", step=0.1, group=group_two_title)/100 // Calculate trailing stop values long_start_trailing_val = strategy.position_avg_price + (strategy.position_avg_price * start_trailing_after) long_trail_behind_val = close - (strategy.position_avg_price * trail_behind) long_stop_loss = strategy.position_avg_price * (1.0 - stop_loss_val) short_start_trailing_val = strategy.position_avg_price - (strategy.position_avg_price * start_trailing_after) short_trail_behind_val = close + (strategy.position_avg_price * trail_behind) short_stop_loss = strategy.position_avg_price * (1 + stop_loss_val) // Calulate EMA EMA = switch EMAtype "EMA" => ta.ema(EMAsource, EMAlength) "SMA" => ta.sma(EMAsource, EMAlength) "RMA" => ta.rma(EMAsource, EMAlength) "WMA" => ta.wma(EMAsource, EMAlength) => na EMA_ = EMAtimeframe == timeframe.period ? EMA : request.security(syminfo.ticker, EMAtimeframe, EMA[1], lookahead = barmerge.lookahead_on) plot(EMA_, title="EMA", linewidth=2, color=blue, editable=true) EMA_cloud_upper_band_val = EMA_ + (EMA_ * openLongEntryAbove/100) EMA_cloud_lower_band_val = EMA_ - (EMA_ * openLongEntryAbove/100) EMA_cloud_upper_band = plot(EMA_cloud_upper_band_val, title="EMA Cloud Upper Band", color=blue) EMA_cloud_lower_band = plot(EMA_cloud_lower_band_val, title="EMA Cloud Upper Band", color=blue) fill(EMA_cloud_upper_band, EMA_cloud_lower_band, editable=false, color=lightBlue) distance_from_EMA = ((close - EMA_)/close)*100 if distance_from_EMA < 0 distance_from_EMA := distance_from_EMA * -1 // Calulate Ladder Entries long_ladder_1_limit_price = close - (close * 1 * ladderStep) long_ladder_2_limit_price = close - (close * 2 * ladderStep) long_ladder_3_limit_price = close - (close * 3 * ladderStep) long_ladder_4_limit_price = close - (close * 4 * ladderStep) short_ladder_1_limit_price = close + (close * 1 * ladderStep) short_ladder_2_limit_price = close + (close * 2 * ladderStep) short_ladder_3_limit_price = close + (close * 3 * ladderStep) short_ladder_4_limit_price = close + (close * 4 * ladderStep) var position_qty = strategy.equity/close if enableLaddering position_qty := (strategy.equity/close) / ladderRungs else position_qty := strategy.equity/close plot(position_qty, color=white) //plot(strategy.equity, color=green) // Entry Conditions currently_in_a_postion = strategy.position_size != 0 currently_in_a_long_postion = strategy.position_size > 0 currently_in_a_short_postion = strategy.position_size < 0 average_price = strategy.position_avg_price bars_since_entry = currently_in_a_postion ? bar_index - strategy.opentrades.entry_bar_index(strategy.opentrades - 1) + 1 : 5 long_run_up = ta.highest(high, bar_index == 0 ? 5000: bars_since_entry) long_run_up_line = plot(long_run_up, style=plot.style_stepline, editable=false, color=currently_in_a_long_postion ? green : transparent) start_trailing_long_entry = currently_in_a_long_postion and long_run_up > long_start_trailing_val long_trailing_stop = start_trailing_long_entry ? long_run_up - (long_run_up * trail_behind) : long_stop_loss long_trailing_stop_line = plot(long_trailing_stop, style=plot.style_stepline, editable=false, color=currently_in_a_long_postion ? long_trailing_stop > strategy.position_avg_price ? green : red : transparent) short_run_up = ta.lowest(low, bar_index == 0 ? 5000: bars_since_entry) short_run_up_line = plot(short_run_up, style=plot.style_stepline, editable=false, color=currently_in_a_short_postion ? green : transparent) start_trailing_short_entry = currently_in_a_short_postion and short_run_up < short_start_trailing_val short_trailing_stop = start_trailing_short_entry ? short_run_up + (short_run_up * trail_behind) : short_stop_loss short_trailing_stop_line = plot(short_trailing_stop, style=plot.style_stepline, editable=false, color=currently_in_a_short_postion ? short_trailing_stop < strategy.position_avg_price ? green : red : transparent) long_conditions_met = distance_from_EMA > openLongEntryAbove and close < EMA_ and not currently_in_a_postion short_conditions_met = distance_from_EMA > openEntryEntryAbove and close > EMA_ and not currently_in_a_postion close_long_entries = distance_from_EMA <= closeEntryBelow or close <= long_trailing_stop close_short_entries = distance_from_EMA <= closeEntryBelow or close >= short_trailing_stop cancel_entries = distance_from_EMA <= cancelEntryBelow plotshape(long_conditions_met ? close : na, style=shape.diamond, title="Long Conditions Met" ) plotshape(short_conditions_met ? close : na, style=shape.diamond, title="Short Conditions Met" ) plot(average_price,style=plot.style_stepline, editable=false, color=currently_in_a_postion ? blue : transparent) // Long Entry if enableLaddering if ladderRungs == 2 strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met) else if ladderRungs == 3 strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 3", direction=strategy.long, qty=position_qty, limit=long_ladder_3_limit_price, when=long_conditions_met) else if ladderRungs == 4 strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 3", direction=strategy.long, qty=position_qty, limit=long_ladder_3_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 4", direction=strategy.long, qty=position_qty, limit=long_ladder_4_limit_price, when=long_conditions_met) strategy.exit(id="Close Long Ladder 1", from_entry="Long Ladder 1", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries) strategy.exit(id="Close Long Ladder 2", from_entry="Long Ladder 2", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries) strategy.exit(id="Close Long Ladder 3", from_entry="Long Ladder 3", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries) strategy.exit(id="Close Long Ladder 4", from_entry="Long Ladder 4", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries) strategy.cancel(id="Long Ladder 1", when=cancel_entries) strategy.cancel(id="Long Ladder 2", when=cancel_entries) strategy.cancel(id="Long Ladder 3", when=cancel_entries) strategy.cancel(id="Long Ladder 4", when=cancel_entries) else strategy.entry(id="Long", direction=strategy.long, qty=100, when=long_conditions_met) strategy.exit(id="Close Long", from_entry="Long", stop=long_stop_loss, limit=EMA_, when=close_long_entries) strategy.cancel(id="Long", when=cancel_entries) // Short Entry if enableLaddering if ladderRungs == 2 strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met) else if ladderRungs == 3 strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 3", direction=strategy.short, qty=position_qty, limit=short_ladder_3_limit_price, when=short_conditions_met) else if ladderRungs == 4 strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 3", direction=strategy.short, qty=position_qty, limit=short_ladder_3_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 4", direction=strategy.short, qty=position_qty, limit=short_ladder_4_limit_price, when=short_conditions_met) strategy.exit(id="Close Short Ladder 1", from_entry="Short Ladder 1", stop=short_trailing_stop, limit=EMA_, when=close_short_entries) strategy.exit(id="Close Short Ladder 2", from_entry="Short Ladder 2", stop=short_trailing_stop, limit=EMA_, when=close_short_entries) strategy.exit(id="Close Short Ladder 3", from_entry="Short Ladder 3", stop=short_trailing_stop, limit=EMA_, when=close_short_entries) strategy.exit(id="Close Short Ladder 4", from_entry="Short Ladder 4", stop=short_trailing_stop, limit=EMA_, when=close_short_entries) strategy.cancel(id="Short Ladder 1", when=cancel_entries) strategy.cancel(id="Short Ladder 2", when=cancel_entries) strategy.cancel(id="Short Ladder 3", when=cancel_entries) strategy.cancel(id="Short Ladder 4", when=cancel_entries) else strategy.entry(id="Short", direction=strategy.short, when=short_conditions_met) strategy.exit(id="Close Short", from_entry="Short", limit=EMA_, when=close_short_entries) strategy.cancel(id="Short", when=cancel_entries)