これは,双均線交差信号に基づく定量取引戦略で,急速指数移動平均 ((EMA) と遅速指数移動平均 ((EMA) の交差によって市場動向を判断し,動的ストップ・ロズ・コントロールと組み合わせてリスクを管理する. 戦略は,パーセントポジション管理を採用し,デフォルトで10%の資金を使用して取引し,動的ストップ・ロズ・価格を設定することで利益を保護し,リスクを管理する.
戦略の核心的な論理は,20周期と50周期の指数移動平均 (EMA) の交差を監視することによってトレンドの変化を認識することです. 急速なEMAが上昇して遅いEMAを横断すると,システムは複数の信号を生成します. ポジションを開設したたびに,システムは,入場価格 (入場価格の1.3倍) と止損価格 (入場価格の0.95倍) に基づいて自動でストップ価格を設定します. このダイナミックなストップ損失の設計は,異なる市場環境に適応して戦略の柔軟性を高めます.
これは,合理的で論理的に明確なトレンド追跡戦略を設計し,双均線交差でトレンドをキャプチャし,ダイナミックなストップ・ロスを使用してリスクを管理する戦略である.戦略の優点は,操作ルールは明確であり,リスクは制御可能であり,中長期の取引システムの基本的枠組みに適合するものである.より多くのフィルタリング条件を追加し,ストップ・ロスを最適化するメカニズムを最適化することにより,この戦略には大きな最適化余地がある.
/*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 ——————————————————————————————————————————————————————