
Chiến lược này dựa trên khái niệm thống kê Z-Score, được sử dụng để xác định sai lệch thống kê của giá so với trung bình địa phương của nó. Chiến lược này tính Z-Score của giá đóng cửa, sau đó áp dụng trung bình di chuyển ngắn hạn và dài hạn để làm mỏng Z-Score.
Cốt lõi của chiến lược là tính toán và áp dụng điểm Z. Điểm Z là một số liệu thống kê được sử dụng để đo độ lệch của một điểm dữ liệu so với trung bình của mẫu, bằng đơn vị chênh lệch tiêu chuẩn. Trong chiến lược này, công thức tính điểm Z là: Z = (giá đóng cửa - SMA ((giá đóng cửa, N)) / STDEV ((giá đóng cửa, N)) Trong đó, N là chu kỳ cơ bản do người dùng định nghĩa.
Quá trình thực hiện chính sách như sau:
Các điều kiện bổ sung bao gồm:
Giải pháp:
Chiến lược giao dịch thống kê giá tối ưu hóa động lực dựa trên chéo xếp hạng Z là một hệ thống giao dịch đơn giản dựa trên các nguyên tắc thống kê, tập trung vào việc bắt được sự lệch và hồi phục của giá so với giá trung bình địa phương của nó. Bằng cách xử lý trơn tru, kiểm soát khoảng cách tín hiệu và lọc động lực, chiến lược này có hiệu quả làm giảm giao dịch tiếng ồn và cải thiện chất lượng tín hiệu.
Tuy nhiên, chiến lược cũng có một số hạn chế, chẳng hạn như sự phụ thuộc vào giả định thống kê, nhạy cảm tham số và quyết định yếu tố đơn. Bằng cách thêm các biện pháp tối ưu hóa như nhận dạng xu hướng, điều chỉnh biến động, phân tích nhiều khung thời gian, cơ chế dừng lỗ, xác nhận khối lượng giao dịch và kết hợp nhiều yếu tố, bạn có thể nâng cao đáng kể tính thô lỗ và hiệu suất của chiến lược.
Nhìn chung, đây là một nền tảng lý thuyết vững chắc, tạo ra một khung chiến lược đơn giản, dễ hiểu và mở rộng, phù hợp với các thành phần cơ bản của hệ thống giao dịch hoặc công cụ giáo dục để giúp các nhà giao dịch hiểu được các ứng dụng của thống kê trong giao dịch.
/*backtest
start: 2024-06-03 00:00:00
end: 2025-06-02 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/
//@version=6
strategy("Price Statistical Strategy-Z Score V 1.01", overlay=true)
// === Enable / Disable Z-Score Strategy Block ===
enableZScore = input.bool(true, title="Enable Smoothed Z-Score Strategy", tooltip="When enabled, this block calculates a smoothed Z-Score of the closing price and generates entry/exit signals based on crossover behavior between short-term and long-term smoothed Z-Scores.\n\nRecommended for quick and classic detection of price deviation from mean.\nSensitive to outliers. Best suited for relatively normal-distributed market conditions.")
// === Z-Score Parameters ===
zBaseLength = input.int(3, minval=1, title="Z-Score Base Period")
shortSmooth = input.int(3, title="Short-Term Smoothing")
longSmooth = input.int(5, title="Long-Term Smoothing")
// === Z-Score Calculation Function ===
f_zscore(src, length) =>
mean = ta.sma(src, length)
std_dev = ta.stdev(src, length)
z = (src - mean) / std_dev
z
// === Z-Score Logic ===
zRaw = f_zscore(close, zBaseLength)
zShort = ta.sma(zRaw, shortSmooth)
zLong = ta.sma(zRaw, longSmooth)
// === Minimum gap between identical signals ===
gapBars = input.int(5, minval=1, title="Bars gap between identical signals", tooltip="Minimum number of bars required between two identical signals (entry or exit). Helps reduce signal noise.")
// === Candle-based momentum filters ===
bullish_3bars = close > close[1] and close[1] > close[2] and close[2] > close[3] and close[3] > close[4]
bearish_3bars = close < close[1] and close[1] < close[2] and close[2] < close[3] and close[3] < close[4]
// === Entry and Exit Logic with minimum signal gap and candle momentum filter ===
var int lastEntryBar = na
var int lastExitBar = na
if enableZScore
longCondition = (zShort > zLong)
exitCondition = (zShort < zLong)
if longCondition and (na(lastEntryBar) or bar_index - lastEntryBar > gapBars) and not bullish_3bars
strategy.entry("Z Score", strategy.long)
lastEntryBar := bar_index
if exitCondition and (na(lastExitBar) or bar_index - lastExitBar > gapBars) and not bearish_3bars
strategy.close("Z Score", comment="Z Score")
lastExitBar := bar_index
// === Real-time PnL Table for Last Open Position ===
var table positionTable = table.new(position.bottom_right, 2, 2, border_width=1)
// Header Labels
table.cell(positionTable, 0, 0, "Entry Price", text_color=color.white, bgcolor=color.gray)
table.cell(positionTable, 1, 0, "Unrealized PnL (%)", text_color=color.white, bgcolor=color.gray)
// Values (only when position is open)
isLong = strategy.position_size > 0
entryPrice = strategy.position_avg_price
unrealizedPnL = isLong ? (close - entryPrice) / entryPrice * 100 : na
// Define dynamic text color for PnL
pnlColor = unrealizedPnL > 0 ? color.green : unrealizedPnL < 0 ? color.red : color.gray
// Update Table Content
if isLong
table.cell(positionTable, 0, 1, str.tostring(entryPrice, "#.####"), text_color=color.gray, bgcolor=color.new(color.gray, 90))
table.cell(positionTable, 1, 1, str.tostring(unrealizedPnL, "#.##") + " %", text_color=pnlColor, bgcolor=color.new(pnlColor, 90))
else
table.cell(positionTable, 0, 1, "—", text_color=color.gray, bgcolor=color.new(color.gray, 90))
table.cell(positionTable, 1, 1, "—", text_color=color.gray, bgcolor=color.new(color.gray, 90))