Chiến lược giá khối lượng tương đối là một chiến lược giao dịch định lượng dựa trên khối lượng giao dịch bất thường và biến động giá. Chiến lược này so sánh khối lượng giao dịch hiện tại với mức trung bình lịch sử để xác định khối lượng giao dịch có bất thường hay không. Nó cũng kết hợp khoảng cách trung bình thực sự để xác định giá có tương đối ổn định hay không. Khi khối lượng giao dịch tăng bất thường và giá tương đối ổn định, nó được coi là tín hiệu nhập cảnh.
Lý thuyết cốt lõi của chiến lược giá khối lượng tương đối dựa trên hai chỉ số để đánh giá: khối lượng giao dịch tương đối và phạm vi biến động giá.
Đầu tiên, chúng tôi tính toán trung bình động đơn giản của khối lượng giao dịch trong 20 giai đoạn gần đây nhất như khối lượng giao dịch trung bình lịch sử. Sau đó chúng tôi đặt một tham số nhiều (chẳng hạn như 1,5 lần). Khi khối lượng giao dịch hiện tại lớn hơn 1,5 lần khối lượng giao dịch trung bình, chúng tôi coi khối lượng giao dịch là bất thường và thuộc về tình huống khối lượng tương đối.
Thứ hai, chúng ta tính toán khoảng trung bình thực sự (ATR) trong 14 giai đoạn gần đây nhất như một thước đo biến động giá. Đồng thời, chúng ta tính toán độ lệch chuẩn của biến động trung bình. Nếu biến động thực tế hiện tại nằm giữa mức trung bình cộng hoặc trừ một độ lệch chuẩn, chúng ta coi sự biến động giá là trong một phạm vi tương đối ổn định.
Khi hai điều kiện trên được đáp ứng cùng một lúc, một tín hiệu dài được phát hành để mở một vị trí dài. Trong thời gian nắm giữ, hai lần ATR được sử dụng như mức dừng lỗ, và giá cao nhất trừ hai lần ATR được sử dụng như mức lấy lợi nhuận.
Lợi thế lớn nhất của chiến lược giá khối lượng tương đối là nó nắm bắt xu hướng giá do khối lượng giao dịch bất thường gây ra. Khi khối lượng giao dịch tăng lên, nó đại diện cho sự thay đổi trong thái độ của những người tham gia thị trường, thường báo hiệu sự đột phá giá và hình thành các xu hướng mới. Bằng cách so sánh mối quan hệ giữa khối lượng giao dịch và trung bình lịch sử, chiến lược có thể xác định hiệu quả thời gian của khối lượng giao dịch bất thường.
Mặt khác, chiến lược cũng xem xét tỷ lệ biến động, do đó các tín hiệu xảy ra trong các giai đoạn giá tương đối ổn định. Điều này tránh được rủi ro mất mát lớn do theo đuổi mức cao trong các biến động dữ dội. Nó cũng làm tăng cơ hội lợi nhuận vì xu hướng thường bắt đầu phá vỡ sau khi ổn định tương đối.
Rủi ro lớn nhất của chiến lược này là chỉ số khối lượng giao dịch không thể chắc chắn 100% về xu hướng mới.
Để giảm tổn thất, điều chỉnh phù hợp các tham số của
Chiến lược có thể được tối ưu hóa trong các khía cạnh sau:
Thêm các chỉ số khác để đánh giá, chẳng hạn như tỷ lệ thay đổi, doanh thu, vv, để làm cho các tín hiệu khối lượng giao dịch bất thường đáng tin cậy hơn.
Các thông số ATR có thể được tối ưu hóa cho các cổ phiếu khác nhau để xác định chính xác hơn phạm vi giá ổn định.
Thêm các thuật toán học máy để tích cực đánh giá khối lượng giao dịch bất thường, không chỉ đơn giản so sánh với mức trung bình lịch sử.
Sử dụng các mô hình học sâu để dự đoán biến động giá, không chỉ dựa trên ATR lịch sử.
Chiến lược giá khối lượng tương đối nắm bắt khối lượng giao dịch bất thường như một tín hiệu đặc trưng và kết hợp phán đoán ổn định giá để phát hành tín hiệu giao dịch. Chiến lược này đơn giản và thực tế, và hoạt động tốt trong việc theo dõi khối lượng giao dịch chứng khoán bất thường.
/*backtest start: 2022-12-21 00:00:00 end: 2023-12-27 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("[KL] Relative Volume + ATR Strategy",overlay=true,pyramiding=1) ENUM_LONG = "Long" // Timeframe { backtest_timeframe_start = input(defval = timestamp("01 Apr 2016 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 // } len_volat = input(14,title="Length of ATR to determine volatility") ATR_volat = atr(len_volat) avg_ATR_volat = sma(ATR_volat, len_volat) std_ATR_volat = stdev(ATR_volat, len_volat) // } // 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)) // } // Signals for entry { _avg_vol = sma(volume,input(20, title="SMA(volume) length (for relative comparison)")) _relative_vol = _avg_vol * input(1.5,title="Multiple of avg vol to consider relative volume as being high",type=input.float) __lowerOfOpenClose = min(open,close) _wickRatio_lower = (__lowerOfOpenClose - low) / (high - low) entry_signal1 = volume > _relative_vol entry_signal2 = ATR_volat < avg_ATR_volat + std_ATR_volat and ATR_volat > avg_ATR_volat - std_ATR_volat // } 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 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // placed before entry, will re-enter if stopped out exit_msg = close <= strategy.position_avg_price ? "stop loss" : "take profit" if strategy.position_size > 0 and TSL_source <= stop_loss_price strategy.close(ENUM_LONG, comment=exit_msg) // ENTRY ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: if entry_signal1 and entry_signal2// and entry_signal3 entry_msg = strategy.position_size > 0 ? "adding" : "initial" strategy.entry(ENUM_LONG, strategy.long, comment=entry_msg) // CLEAN UP: if strategy.position_size == 0 stop_loss_price := float(0)