Il s'agit d'une stratégie de négociation quantitative basée sur des signaux croisés doubles EMA, qui utilise l'intersection des moyennes mobiles exponentielles (EMA) rapides et lentes pour déterminer les tendances du marché, combinée à des contrôles dynamiques de prise de profit et de stop-loss pour la gestion des risques.
La logique de base tourne autour de la surveillance des croisements entre les EMA de 20 périodes et 50 périodes pour identifier les changements de tendance. Une position longue est initiée lorsque l'EMA rapide traverse au-dessus de l'EMA lente. À l'entrée, le système définit automatiquement les niveaux de prise de profit (1,3 fois le prix d'entrée) et les niveaux de stop-loss (0,95 fois le prix d'entrée). Cette conception dynamique de contrôle profit/perte s'adapte aux différentes conditions du marché, améliorant la flexibilité de la stratégie.
Il s'agit d'une stratégie de suivi des tendances bien conçue avec une logique claire, utilisant des croisements doubles EMA pour la capture des tendances et des contrôles dynamiques des profits / pertes pour la gestion des risques. Les atouts de la stratégie résident dans ses règles claires et son risque contrôlé, ce qui la rend adaptée comme base pour les systèmes de trading à moyen et long terme. Il y a une marge d'optimisation significative grâce à des filtres supplémentaires et des mécanismes de profit / perte améliorés. Les traders doivent valider la stratégie en effectuant des backtests dans différentes conditions de marché et ajuster les paramètres en fonction de leur tolérance au risque avant la mise en œuvre en direct.
/*backtest start: 2019-12-23 08:00:00 end: 2024-12-09 08:00:00 period: 1d basePeriod: 1d 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/ // © Pineify //======================================================================// // ____ _ _ __ // // | _ \(_)_ __ ___(_)/ _|_ _ // // | |_) | | '_ \ / _ \ | |_| | | | // // | __/| | | | | __/ | _| |_| | // // |_| |_|_| |_|\___|_|_| \__, | // // |___/ // //======================================================================// //@version=5 strategy(title="TQQQ EMA Strategy", overlay=true) //#region —————————————————————————————————————————————————— Common Dependence p_comm_time_range_to_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) => int start_unix_time = na int end_unix_time = na int start_time_hour = na int start_time_minute = na int end_time_hour = na int end_time_minute = na if str.length(time_range) == 11 // Format: hh:mm-hh:mm start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2))) start_time_minute := math.floor(str.tonumber(str.substring(time_range, 3, 5))) end_time_hour := math.floor(str.tonumber(str.substring(time_range, 6, 8))) end_time_minute := math.floor(str.tonumber(str.substring(time_range, 9, 11))) else if str.length(time_range) == 9 // Format: hhmm-hhmm start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2))) start_time_minute := math.floor(str.tonumber(str.substring(time_range, 2, 4))) end_time_hour := math.floor(str.tonumber(str.substring(time_range, 5, 7))) end_time_minute := math.floor(str.tonumber(str.substring(time_range, 7, 9))) start_unix_time := timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), start_time_hour, start_time_minute, 0) end_unix_time := timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), end_time_hour, end_time_minute, 0) [start_unix_time, end_unix_time] p_comm_time_range_to_start_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) => int start_time_hour = na int start_time_minute = na if str.length(time_range) == 11 // Format: hh:mm-hh:mm start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2))) start_time_minute := math.floor(str.tonumber(str.substring(time_range, 3, 5))) else if str.length(time_range) == 9 // Format: hhmm-hhmm start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2))) start_time_minute := math.floor(str.tonumber(str.substring(time_range, 2, 4))) timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), start_time_hour, start_time_minute, 0) p_comm_time_range_to_end_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) => int end_time_hour = na int end_time_minute = na if str.length(time_range) == 11 end_time_hour := math.floor(str.tonumber(str.substring(time_range, 6, 8))) end_time_minute := math.floor(str.tonumber(str.substring(time_range, 9, 11))) else if str.length(time_range) == 9 end_time_hour := math.floor(str.tonumber(str.substring(time_range, 5, 7))) end_time_minute := math.floor(str.tonumber(str.substring(time_range, 7, 9))) timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), end_time_hour, end_time_minute, 0) p_comm_timeframe_to_seconds(simple string tf) => float seconds = 0 tf_lower = str.lower(tf) value = str.tonumber(str.substring(tf_lower, 0, str.length(tf_lower) - 1)) if str.endswith(tf_lower, 's') seconds := value else if str.endswith(tf_lower, 'd') seconds := value * 86400 else if str.endswith(tf_lower, 'w') seconds := value * 604800 else if str.endswith(tf_lower, 'm') seconds := value * 2592000 else seconds := str.tonumber(tf_lower) * 60 seconds p_custom_sources() => [open, high, low, close, volume] //#endregion ————————————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Ta Dependence //#endregion ————————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Constants // Input Groups string P_GP_1 = "" //#endregion ————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Inputs // Default int p_inp_1 = input.int(defval=20, title="Fast EMA Length", group=P_GP_1) int p_inp_2 = input.int(defval=50, title="Slow EMA Length", group=P_GP_1) float p_inp_3 = input.float(defval=1.3, title="Take Profit Price Multiplier", group=P_GP_1, step=0.01) float p_inp_4 = input.float(defval=0.95, title="Stop Loss Price Multiplier", group=P_GP_1, step=0.01) //#endregion ——————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Price Data //#endregion ——————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Indicators p_ind_1 = ta.ema(close, p_inp_1) // Fast EMA p_ind_2 = ta.ema(close, p_inp_2) // Slow EMA //#endregion ——————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Conditions p_cond_1 = (ta.crossover(p_ind_1, p_ind_2)) //#endregion ——————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Strategy // Strategy Order Variables string p_st_name_1 = "Entry" string p_st_name_2 = "Exit" var float p_st_name_2_tp = na var bool p_st_name_2_tp_can_drawing = true var float p_st_name_2_sl = na var bool p_st_name_2_sl_can_drawing = true // Strategy Global open_trades_number = strategy.opentrades pre_bar_open_trades_number = na(open_trades_number[1]) ? 0 : open_trades_number[1] var p_entry_order_id = 1 p_can_place_entry_order() => strategy.equity > 0 get_entry_id_name(int current_order_id, string name) => "[" + str.tostring(current_order_id) + "] " + name is_entry_order(string order_id, string name) => str.startswith(order_id, "[") and str.endswith(order_id, "] " + name) get_open_trades_entry_ids() => int p_open_trades_count = strategy.opentrades string[] p_entry_ids = array.new_string(0, "") if p_open_trades_count > 0 for i = 0 to p_open_trades_count - 1 array.push(p_entry_ids, strategy.opentrades.entry_id(i)) p_entry_ids // Entry (Entry) if p_cond_1 and p_can_place_entry_order() p_st_name_1_id = get_entry_id_name(p_entry_order_id, p_st_name_1) p_entry_order_id := p_entry_order_id + 1 string entry_message = "" strategy.entry(id=p_st_name_1_id, direction=strategy.long, alert_message=entry_message, comment=p_st_name_1_id) // TP/SL Exit (Exit) float p_st_name_2_limit = close * p_inp_3 if p_st_name_2_tp_can_drawing p_st_name_2_tp_can_drawing := false p_st_name_2_tp := p_st_name_2_limit float p_st_name_2_stop = close * p_inp_4 if p_st_name_2_sl_can_drawing p_st_name_2_sl_can_drawing := false p_st_name_2_sl := p_st_name_2_stop string p_st_name_2_alert_message = "" strategy.exit(id=p_st_name_1_id + "_0", from_entry=p_st_name_1_id, qty_percent=100, limit=p_st_name_2_limit, stop=p_st_name_2_stop, comment_profit=p_st_name_2 + " - TP", comment_loss=p_st_name_2 + " - SL", alert_message=p_st_name_2_alert_message) if high >= p_st_name_2_tp or (pre_bar_open_trades_number > 0 and open_trades_number == 0) p_st_name_2_tp_can_drawing := true p_st_name_2_sl_can_drawing := true p_st_name_2_tp := na p_st_name_2_sl := na plot(p_st_name_2_tp, title="Exit - TP", color=color.rgb(0, 150, 136, 0), linewidth=1, style = plot.style_circles) if low <= p_st_name_2_sl or (pre_bar_open_trades_number > 0 and open_trades_number == 0) p_st_name_2_sl_can_drawing := true p_st_name_2_tp_can_drawing := true p_st_name_2_sl := na p_st_name_2_tp := na plot(p_st_name_2_sl, title="Exit - SL", color=color.rgb(244, 67, 54, 0), linewidth=1, style = plot.style_circles) //#endregion ————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Indicator Plots // Fast EMA plot(p_ind_1, "Fast EMA", color.rgb(33, 150, 243, 0), 1) // Slow EMA plot(p_ind_2, "Slow EMA", color.rgb(255, 82, 82, 0), 1) //#endregion ———————————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Custom Plots //#endregion ————————————————————————————————————————————————————————————— //#region —————————————————————————————————————————————————— Alert //#endregion ——————————————————————————————————————————————————————