Chiến lược này là một hệ thống giao dịch dựa trên nhiều chỉ báo kỹ thuật, chủ yếu kết hợp ba thành phần cốt lõi: đường trung bình động hàm mũ (EMA), chỉ số sức mạnh tương đối (RSI) và tính toán khoảng cách. Chiến lược này theo dõi động lực và sức mạnh xu hướng thị trường một cách linh hoạt, đồng thời duy trì sự ổn định của tín hiệu và tránh được các đột phá giả và điều kiện thị trường biến động. Hệ thống áp dụng cơ chế xác nhận nhiều lần và đưa ra phán đoán chính xác về tình trạng thị trường bằng cách tính toán khoảng cách tương đối và ngưỡng động giữa các chỉ số.
Chiến lược này sử dụng bốn đường EMA ở các giai đoạn khác nhau (giai đoạn 5, 13, 40 và 55) để xây dựng khuôn khổ xu hướng và sử dụng chỉ báo RSI (14 giai đoạn) để tăng cường khả năng phán đoán hướng đi của thị trường. Cụ thể:
Chiến lược này kiểm soát rủi ro hiệu quả trong khi vẫn duy trì sự ổn định của tín hiệu thông qua sự phối hợp của nhiều chỉ báo kỹ thuật. Thiết kế hệ thống hoàn toàn xem xét tính đa dạng của thị trường và áp dụng phương pháp tính ngưỡng động và khoảng cách để cải thiện khả năng thích ứng. Thông qua quá trình tối ưu hóa và cải tiến liên tục, chiến lược này được kỳ vọng sẽ duy trì hiệu suất ổn định trong nhiều môi trường thị trường khác nhau.
/*backtest
start: 2019-12-23 08:00:00
end: 2025-01-04 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=6
strategy("EMA Crossover Strategy with RSI Average, Distance, and Signal Persistence", overlay=true, fill_orders_on_standard_ohlc=true)
// Define EMAs
ema5 = ta.ema(close, 5)
ema13 = ta.ema(close, 13)
ema40 = ta.ema(close, 40)
ema55 = ta.ema(close, 55)
// Calculate 14-period RSI
rsi = ta.rsi(close, 14)
// Calculate the RSI average
averageRsiLength = 14 // Length for RSI average
averageRsi = ta.sma(rsi, averageRsiLength)
// Define conditions
emaShortTermCondition = ema5 > ema13 // EMA 5 > EMA 13
emaLongTermCondition = ema40 > ema55 // EMA 40 > EMA 55
rsiCondition = rsi > 50 and rsi > averageRsi // RSI > 50 and RSI > average RSI
// Track the distance between ema5 and ema13 for the last 5 candles
distance = math.abs(ema5 - ema13)
distanceWindow = 5
distances = array.new_float(distanceWindow, 0.0)
array.shift(distances)
array.push(distances, distance)
// Calculate the average distance of the last 5 distances
avgDistance = array.avg(distances)
// Track distance between EMA40 and EMA13 for the last few candles
distance40_13 = math.abs(ema40 - ema13)
distanceWindow40_13 = 5
distances40_13 = array.new_float(distanceWindow40_13, 0.0)
array.shift(distances40_13)
array.push(distances40_13, distance40_13)
// Calculate the average distance for EMA40 and EMA13
avgDistance40_13 = array.avg(distances40_13)
// Neutral condition: if the current distance is lower than the average of the last 5 distances
neutralCondition = distance < avgDistance or ema13 > ema5
// Short signal condition: EMA40 crosses above EMA55
shortCondition = ema40 > ema55
// Conditions for Green and Red signals (based on RSI thresholds)
greenSignalCondition = rsi > 60 // Green if RSI > 60, regardless of EMAs
redSignalCondition = rsi < 40 // Red if RSI < 40, regardless of EMAs
// Combine conditions for a buy signal (Long)
longCondition = emaShortTermCondition and emaLongTermCondition and rsiCondition and not neutralCondition
// Store the last signal (initialized as na)
var string lastSignal = na
// Track previous distance between EMA40 and EMA13
var float prevDistance40_13 = na
// Check if the current distance between EMA40 and EMA13 is greater than the previous
distanceCondition = (not na(prevDistance40_13)) ? (distance40_13 > prevDistance40_13) : true
// Update the lastSignal only if the current candle closes above EMA5, otherwise recalculate it
if (close > ema5)
if (longCondition and distanceCondition)
lastSignal := "long"
else if (shortCondition and distanceCondition)
lastSignal := "short"
else if (neutralCondition)
lastSignal := "neutral"
// Add green signal based on RSI
else if (greenSignalCondition)
lastSignal := "green"
// Add red signal based on RSI
else if (redSignalCondition)
lastSignal := "red"
// If current candle doesn't close above EMA5, recalculate the signal based on current conditions
if (close <= ema5)
if (longCondition)
lastSignal := "long"
else if (shortCondition)
lastSignal := "short"
else if (greenSignalCondition)
lastSignal := "green"
else if (redSignalCondition)
lastSignal := "red"
else
lastSignal := "neutral"
// Update previous distance for next comparison
prevDistance40_13 := distance40_13
// Set signal conditions based on lastSignal
isLong = lastSignal == "long"
isShort = lastSignal == "short"
isNeutral = lastSignal == "neutral"
isGreen = lastSignal == "green"
isRed = lastSignal == "red"
// Plot signals with preference for long (green) and short (red), no multiple signals per bar
plotshape(isLong, style=shape.circle, color=color.green, location=location.belowbar, size=size.tiny)
plotshape(isShort and not isLong, style=shape.circle, color=color.red, location=location.abovebar, size=size.tiny)
plotshape(isNeutral and not isLong and not isShort, style=shape.circle, color=color.gray, location=location.abovebar, size=size.tiny)
plotshape(isGreen and not isLong and not isShort and not isNeutral, style=shape.circle, color=color.green, location=location.belowbar, size=size.tiny)
plotshape(isRed and not isLong and not isShort and not isNeutral, style=shape.circle, color=color.red, location=location.abovebar, size=size.tiny)
// Plot EMAs for visualization
plot(ema5, color=color.blue, title="EMA 5")
plot(ema13, color=color.orange, title="EMA 13")
plot(ema40, color=color.green, title="EMA 40")
plot(ema55, color=color.red, title="EMA 55")
// Plot RSI average for debugging (optional, remove if not needed)
// plot(averageRsi, title="Average RSI", color=color.orange)
// hline(50, title="RSI 50", color=color.gray) // Optional: Comment this out too if not needed
if isLong
strategy.entry("Enter Long", strategy.long)
else if isShort
strategy.entry("Enter Short", strategy.short)