
Chiến lược giá tương đối là một chiến lược giao dịch định lượng dựa trên sự bất thường về khối lượng giao dịch và biến động giá. Chiến lược này đánh giá khối lượng giao dịch là bất thường bằng cách so sánh khối lượng giao dịch hiện tại với mối quan hệ của khối lượng giao dịch trung bình trong lịch sử; đồng thời kết hợp với phạm vi sóng thực trung bình để đánh giá giá có nằm trong phạm vi tương đối ổn định hay không.
Lý luận cốt lõi của chiến lược giá tương đối dựa trên hai chỉ số, một là khối lượng giao dịch tương đối và một là phạm vi biến động giá.
Đầu tiên, chúng tôi tính toán trung bình di chuyển đơn giản của khối lượng giao dịch trong 20 chu kỳ gần đây nhất, làm trung bình giao dịch lịch sử. Sau đó, chúng tôi đặt một tham số nhân (ví dụ: 1,5 lần), khi khối lượng giao dịch hiện tại lớn hơn khối lượng giao dịch trung bình 1,5 lần, chúng tôi cho rằng khối lượng giao dịch là bất thường, thuộc trường hợp khối lượng giao dịch tương đối lớn.
Tiếp theo, chúng ta tính trung bình tần số thực (ATR) trong 14 chu kỳ gần nhất như là một thước đo của biến động giá. Đồng thời tính chênh lệch chuẩn của tần số thực trung bình, nếu tần số thực hiện tại nằm giữa trung bình tích cực và một chênh lệch chuẩn, chúng ta cho rằng biến động giá nằm trong khoảng tương đối ổn định.
Khi cả hai điều kiện trên được đáp ứng cùng một lúc, tức là phát đi nhiều tín hiệu, mở nhiều vị trí. Trong quá trình giữ vị trí, hãy lấy ATR tối đa của điểm thấp trừ ATR gấp đôi như là vị trí dừng lỗ, lấy ATR tối đa của điểm cao trừ ATR gấp đôi như là vị trí dừng.
Lợi thế lớn nhất của chiến lược giá tương đối là nắm bắt xu hướng giá do khối lượng giao dịch bất thường. Khi khối lượng giao dịch tăng lên, nó đại diện cho sự thay đổi thái độ của người tham gia thị trường, thường là dấu hiệu của sự đột phá của giá và sự hình thành của xu hướng mới.
Mặt khác, chiến lược cũng tính đến tỷ lệ dao động của giá, khiến tín hiệu xảy ra vào thời điểm giá tương đối ổn định. Điều này tránh rủi ro mất mát lớn do đuổi theo khi dao động mạnh. Đồng thời, nó cũng làm tăng cơ hội kiếm lợi nhuận, vì xu hướng thường chỉ bắt đầu phá vỡ sau khi tương đối ổn định.
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ể xác định 100% xu hướng mới, khối lượng giao dịch tăng có thể là đột phá giả, giá sẽ nhanh chóng đảo ngược. Trong trường hợp này, chiến lược này chịu tổn thất lớn hơn.
Để giảm tổn thất, bạn có thể điều chỉnh thích hợp các tham số về lượng giao dịch tương đối, đặt tiêu chuẩn nghiêm ngặt hơn cho phán đoán về khối lượng giao dịch bất thường. Hoặc thêm các chỉ số phán đoán khác, chẳng hạn như tăng phân tích khối lượng giao dịch, để đánh giá liệu sự tăng trưởng khối lượng giao dịch có phù hợp với số lượng giao dịch hay không.
Chiến lược này có thể được tối ưu hóa theo các khía cạnh sau:
Thêm các chỉ số khác, chẳng hạn như giá trị giao dịch, giá trị giao dịch, để tín hiệu giao dịch bất thường trở nên đáng tin cậy hơn.
Các tham 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 khoảng ổn định giá.
Thêm các thuật toán học máy để đánh giá tích cực các bất thường về khối lượng giao dịch thay vì chỉ đơn giản so sánh với các giá trị trung bình lịch sử.
Sử dụng 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á tương đối phát ra tín hiệu giao dịch bằng cách nắm bắt khối lượng giao dịch bất thường làm tín hiệu đặc trưng, kết hợp với phán đoán ổn định giá. Chiến lược đơn giản và thực tế, hiệu quả hơn khi theo dõi khối lượng giao dịch bất thường của cổ phiếu. Nhưng cũng có một số rủi ro tín hiệu giả, cần tối ưu hóa các chỉ số hơn nữa để tăng hiệu quả.
/*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)