
Chiến lược này là một hệ thống giao dịch kết hợp các tín hiệu chéo đồng đều với bộ lọc trạng thái thị trường. Nó nắm bắt xu hướng thị trường bằng cách chéo giữa trung bình di chuyển đơn giản 9 chu kỳ và 21 chu kỳ (SMA), đồng thời sử dụng chỉ số hướng trung bình (ADX) và chỉ số hỗn loạn (Choppiness Index, CI) để lọc môi trường thị trường, đảm bảo giao dịch chỉ trong thị trường có xu hướng rõ ràng và có tính năng biến động tốt.
Chiến lược này bao gồm 3 phần quan trọng:
Chiến lược sử dụng các phương pháp tính toán chỉ số kỹ thuật tối ưu, bao gồm hàm cộng, tính toán giá trị tối đa và giá trị tối thiểu tùy chỉnh và tính toán tần số thực chuẩn (TR) để đảm bảo độ chính xác và hiệu quả tính toán của tín hiệu.
Chiến lược này xây dựng một hệ thống giao dịch hoàn chỉnh bằng cách kết hợp chiến lược giao dịch đồng tuyến cổ điển với các chỉ số kỹ thuật hiện đại. Nó không chỉ tập trung vào việc nắm bắt xu hướng, mà còn đặc biệt chú ý đến sự phù hợp của môi trường thị trường, tăng sự ổn định của giao dịch thông qua cơ chế lọc đa dạng. Mặc dù có một số vấn đề nhạy cảm và chậm trễ về tham số, chiến lược vẫn có nhiều chỗ cải thiện thông qua hướng tối ưu hóa được đề xuất.
/*backtest
start: 2024-02-22 00:00:00
end: 2024-12-06 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
*/
//@version=6
strategy("MA9/MA21 Cross with ADX & CHOP Filter", overlay=true, initial_capital=10000, currency=currency.USD)
// ─── CUSTOM FUNCTIONS ──────────────────────────────────────────────────────
// Custom function to compute the sum over the last 'len' bars.
f_sum(src, len) =>
s = 0.0
for i = 0 to len - 1
s += src[i]
s
// Custom function to compute the highest value over the last 'len' bars.
f_highest(src, len) =>
h = src[0]
for i = 1 to len - 1
h := math.max(h, src[i])
h
// Custom function to compute the lowest value over the last 'len' bars.
f_lowest(src, len) =>
l = src[0]
for i = 1 to len - 1
l := math.min(l, src[i])
l
// ─── INPUTS ──────────────────────────────────────────────────────────────
ma9Period = input.int(9, title="MA 9 Period", minval=1)
ma21Period = input.int(21, title="MA 21 Period", minval=1)
adxLength = input.int(7, title="ADX Smoothing / DI Length", minval=1)
adxThresh = input.float(20.0, title="ADX Threshold", step=0.1)
chopLen = input.int(7, title="CHOP Length", minval=1)
chopOff = input.int(0, title="CHOP Offset", minval=0) // Not applied in calculation
chopThresh = input.float(50.0, title="CHOP Maximum (do not trade if above)", step=0.1)
// ─── CALCULATE INDICATORS ────────────────────────────────────────────────────
// Moving Averages
ma9 = ta.sma(close, ma9Period)
ma21 = ta.sma(close, ma21Period)
// --- True Range Calculation ---
// Manual implementation of true range (tr)
tr = math.max(math.max(high - low, math.abs(high - nz(close[1]))), math.abs(low - nz(close[1])))
// --- ADX Calculation (Manual Implementation) ---
// Calculate directional movements
upMove = high - nz(high[1])
downMove = nz(low[1]) - low
plusDM = (upMove > downMove and upMove > 0) ? upMove : 0.0
minusDM = (downMove > upMove and downMove > 0) ? downMove : 0.0
// Smooth the values using the built-in rma function
atr = ta.rma(tr, adxLength)
plusDI = 100 * ta.rma(plusDM, adxLength) / atr
minusDI = 100 * ta.rma(minusDM, adxLength) / atr
dx = 100 * math.abs(plusDI - minusDI) / (plusDI + minusDI)
adxValue = ta.rma(dx, adxLength)
// --- Choppiness Index Calculation ---
// Compute the sum of true range over chopLen periods
atrSum = f_sum(tr, chopLen)
// Compute highest high and lowest low over chopLen periods using custom functions
highestHigh = f_highest(high, chopLen)
lowestLow = f_lowest(low, chopLen)
priceRange = highestHigh - lowestLow
chop = priceRange != 0 ? 100 * math.log(atrSum / priceRange) / math.log(chopLen) : 0
// ─── STRATEGY CONDITIONS ─────────────────────────────────────────────────────
// MA Crossover Signals
longCond = ta.crossover(ma9, ma21)
shortCond = ta.crossunder(ma9, ma21)
// Filter: Only trade if ADX > threshold and CHOP ≤ threshold.
filterCond = (adxValue > adxThresh) and (chop <= chopThresh)
// Entries and Exits
if longCond and filterCond
strategy.entry("Long", strategy.long)
if shortCond and filterCond
strategy.entry("Short", strategy.short)
if shortCond
strategy.close("Long")
if longCond
strategy.close("Short")
// ─── PLOTTING ──────────────────────────────────────────────────────────────
plot(ma9, color=color.red, title="MA 9")
plot(ma21, color=color.blue, title="MA 21")
plot(adxValue, title="ADX", color=color.purple)
hline(adxThresh, title="ADX Threshold", color=color.purple, linestyle=hline.style_dotted)
plot(chop, title="CHOP", color=color.orange)
hline(chopThresh, title="CHOP Threshold", color=color.orange, linestyle=hline.style_dotted)