Chiến lược này sử dụng chỉ số hướng trung bình (DI +) và chỉ số hướng tiêu cực (DI-) trên hai khung thời gian để xác định hướng xu hướng cho các giao dịch dài và ngắn. Khi DI + cao hơn DI - trên cả hai khung thời gian lớn và nhỏ hơn, nó chỉ ra xu hướng tăng và tín hiệu dài được kích hoạt. Khi DI - cao hơn DI + trên cả hai khung thời gian, nó chỉ ra xu hướng giảm và tín hiệu ngắn được kích hoạt.
Chiến lược dựa trên một số nguyên tắc:
Tính toán DI + và DI-. Nhận DI + và DI- bằng cách sử dụng giá cao, gần và thấp.
So sánh DI + và DI- trên hai khung thời gian. Tính toán DI + và DI- tương ứng trên khung thời gian biểu chính (ví dụ 1 giờ) và khung thời gian lớn hơn (ví dụ hàng ngày). So sánh các giá trị giữa hai khung thời gian.
Xác định hướng xu hướng. Khi DI + lớn hơn DI- trên cả hai khung thời gian lớn và nhỏ hơn, nó cho thấy xu hướng tăng. Khi DI- lớn hơn DI + trên cả hai khung thời gian, nó cho thấy xu hướng giảm.
DI+>DI- trên cả hai khung cung cấp tín hiệu dài DI->DI+ trên cả hai khung cung cấp tín hiệu ngắn
Thiết lập stop loss. Sử dụng ATR để tính toán stop loss động để theo xu hướng.
Điều kiện thoát. thoát khi dừng lỗ bị tấn công hoặc giá đảo ngược.
Chiến lược có những lợi thế sau:
Sử dụng khung thời gian hai DI lọc ra một số sự đột phá sai.
ATR trailing stop tối đa hóa bảo vệ lợi nhuận và tránh dừng quá chặt.
Dừng lỗ kịp thời kiểm soát lỗ trên các giao dịch đơn.
Giao dịch theo xu hướng cho phép liên tục bắt được xu hướng.
Quy tắc đơn giản và rõ ràng, dễ thực hiện cho giao dịch trực tiếp.
Ngoài ra còn có một số rủi ro:
DI có hiệu ứng chậm trễ, có thể bỏ lỡ thời gian nhập. Có thể tối ưu hóa các thông số hoặc thêm các chỉ số khác.
Khung thời gian kép có thể có sự khác biệt giữa TF lớn hơn và nhỏ hơn. Thêm xác nhận khung thời gian nhiều hơn.
Giữ lỗ quá mạnh có thể gây ra giao dịch quá mức.
Whipsaw trong thị trường bên có thể gây ra các giao dịch thường xuyên.
Tối ưu hóa tham số dựa trên dữ liệu lịch sử và có thể bị quá tải. Đánh giá độ bền của tham số một cách thận trọng.
Chiến lược có thể được cải thiện trong các khía cạnh sau:
Tối ưu hóa các tham số tính toán DI cho bộ tham số tốt nhất.
Thêm các bộ lọc chỉ số khác để cải thiện độ chính xác tín hiệu, ví dụ: MACD, KDJ v.v.
Cải thiện chiến lược dừng lỗ để thích nghi với nhiều điều kiện thị trường hơn, chẳng hạn như dừng lại hoặc lệnh đang chờ.
Thêm các bộ lọc phiên giao dịch để tránh các sự kiện tin tức quan trọng.
Kiểm tra độ bền của tham số trên các sản phẩm khác nhau để cải thiện khả năng thích nghi.
giới thiệu máy học để đào tạo mô hình trên dữ liệu lịch sử.
Tóm lại, đây là một chiến lược theo xu hướng điển hình sử dụng DI để xác định hướng xu hướng và đặt dừng lỗ để khóa lợi nhuận dọc theo xu hướng. Ưu điểm nằm trong logic rõ ràng và dễ thực hiện cho giao dịch trực tiếp.
/*backtest start: 2022-10-31 00:00:00 end: 2023-11-06 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("DI+/- multi TF Strat [KL]", overlay=true, pyramiding=1, initial_capital=1000000000, default_qty_type=strategy.percent_of_equity, default_qty_value=5) var string GROUP_ALERT = "Alerts" var string GROUP_SL = "Stop loss" var string GROUP_ORDER = "Order size" var string GROUP_TP = "Profit taking" var string GROUP_HORIZON = "Time horizon of backtests" var string GROUP_IND = "Directional IndicatorDI+ DI-" // ADX Indicator { adx_len = input(14, group=GROUP_IND, tooltip="Typically 14") tf1 = input.timeframe("", title="DI +/- in Timeframe 1", group=GROUP_IND, tooltip="Main: DI+ > DI-") tf2 = input.timeframe("1D", title="DI +/- in Timeframe 2", group=GROUP_IND, tooltip="Confirmation: DI+ > DI-") // adx_thres = input(20, group=GROUP_IND) //threshold not used in this strategy get_ADX(_high, _close, _low) => // (high, close, mid) -> [plus_DM, minus_DM] // Based on TradingView user BeikabuOyaji's implementation _tr = math.max(math.max(_high - _low, math.abs(_high - nz(_close[1]))), math.abs(_low - nz(_close[1]))) smooth_tr = 0.0 smooth_tr := nz(smooth_tr[1]) - nz(smooth_tr[1]) / adx_len + _tr smooth_directional_mov_plus = 0.0 smooth_directional_mov_plus := nz(smooth_directional_mov_plus[1]) - nz(smooth_directional_mov_plus[1]) / adx_len + (_high - nz(_high[1]) > nz(_low[1]) - _low ? math.max(_high - nz(_high[1]), 0) : 0) smooth_directional_mov_minus = 0.0 smooth_directional_mov_minus := nz(smooth_directional_mov_minus[1]) - nz(smooth_directional_mov_minus[1]) / adx_len + (nz(_low[1]) - _low > _high - nz(_high[1]) ? math.max(nz(_low[1]) - _low, 0) : 0) plus_DM = smooth_directional_mov_plus / smooth_tr * 100 minus_DM = smooth_directional_mov_minus / smooth_tr * 100 // DX = math.abs(plus_DM - minus_DM) / (plus_DM + minus_DM) * 100 // DX not used in this strategy [plus_DM, minus_DM] // DI +/- from timeframes 1 and 2 [plus_DM_tf1, minus_DM_tf1] = get_ADX(request.security(syminfo.tickerid, tf1, high), request.security(syminfo.tickerid, tf1, close),request.security(syminfo.tickerid, tf1, low)) [plus_DM_tf2, minus_DM_tf2] = get_ADX(request.security(syminfo.tickerid, tf2, high),request.security(syminfo.tickerid, tf2, close),request.security(syminfo.tickerid, tf2, low)) // } end of block: ADX Indicator var string ENUM_LONG = "LONG" var string LONG_MSG_ENTER = input.string("Long entered", title="Alert MSG for buying (Long position)", group=GROUP_ALERT) var string LONG_MSG_EXIT = input.string("Long closed", title="Alert MSG for closing (Long position)", group=GROUP_ALERT) backtest_timeframe_start = input(defval=timestamp("01 Apr 2020 13:30 +0000"), title="Backtest Start Time", group=GROUP_HORIZON) within_timeframe = true // Signals for entry _uptrend_confirmed = plus_DM_tf1 > minus_DM_tf1 and plus_DM_tf2 > minus_DM_tf2 entry_signal_long = _uptrend_confirmed plotshape(_uptrend_confirmed, style=shape.triangleup, location=location.bottom, color=color.green) plotshape(not _uptrend_confirmed, style=shape.triangledown, location=location.bottom, color=color.red) // Trailing stop loss ("TSL") { tsl_multi = input.float(2.0, title="ATR Multiplier for trailing stoploss", group=GROUP_SL) SL_buffer = ta.atr(input.int(14, title="Length of ATR for trailing stoploss", group=GROUP_SL)) * tsl_multi TSL_source_long = low var stop_loss_price_long = float(0) var pos_opened_long = false stop_loss_price_long := pos_opened_long ? math.max(stop_loss_price_long, TSL_source_long - SL_buffer) : TSL_source_long - SL_buffer // MAIN: { if pos_opened_long and TSL_source_long <= stop_loss_price_long pos_opened_long := false alert(LONG_MSG_EXIT, alert.freq_once_per_bar) strategy.close(ENUM_LONG, comment=close < strategy.position_avg_price ? "stop loss" : "take profit") // (2) Update the stoploss to latest trailing amt. if pos_opened_long strategy.exit(ENUM_LONG, stop=stop_loss_price_long, comment="SL") // (3) INITIAL ENTRY: if within_timeframe and entry_signal_long pos_opened_long := true alert(LONG_MSG_ENTER, alert.freq_once_per_bar) strategy.entry(ENUM_LONG, strategy.long, comment="long") // Plotting: TSL_transp_long = pos_opened_long and within_timeframe ? 0 : 100 plot(stop_loss_price_long, color=color.new(color.green, TSL_transp_long)) // CLEAN UP: Setting variables back to default values once no longer in use if ta.change(strategy.position_size) and strategy.position_size == 0 pos_opened_long := false if not pos_opened_long stop_loss_price_long := float(0) // } end of MAIN block