
Ý tưởng cốt lõi của chiến lược này là kết hợp chỉ số siêu xu hướng với giao dịch đường cong giá trị ròng, khi chỉ số siêu xu hướng phát ra tín hiệu mua hoặc bán, chúng tôi không thực hiện giao dịch trực tiếp, nhưng đánh giá xem đường cong giá trị ròng hiện tại có thấp hơn đường cong giá trị ròng của nó không. Chúng tôi sẽ chỉ mở vị trí khi đường cong giá trị ròng cao hơn đường cong giá trị ròng.
Chiến lược này bao gồm hai phần chính:
Công thức tính toán cho chỉ số siêu xu hướng là:
Đường lên = giá nguồn - ATR nhân * ATR Đường sắt dưới = giá nguồn + ATR nhân * ATR
Trong đó, ATR biểu thị mức sóng thực trung bình. Chỉ số siêu xu hướng sử dụng ATR để thiết lập đường lên đường xuống, báo hiệu bán khi giá phá vỡ đường lên và mua khi giá phá vỡ đường xuống.
Ý tưởng của việc giao dịch theo đường cong giá trị ròng là chúng ta thực hiện trung bình di chuyển trên đường cong giá trị ròng của chiến lược, tạm dừng giao dịch theo chiến lược hiện tại khi đường cong giá trị ròng thấp hơn đường cong giá trị ròng và mở lại giao dịch khi đường cong giá trị ròng tăng trở lại trên đường cong giá trị ròng.
Chiến lược này kết hợp cả hai, sau khi chỉ số siêu xu hướng tạo ra tín hiệu giao dịch, chúng tôi không giao dịch trực tiếp, nhưng đánh giá xem đường cong giá trị ròng hiện tại có cao hơn đường trung bình di chuyển hay không. Chỉ khi cả hai điều kiện này được đáp ứng, chúng tôi sẽ mở vị trí. Điều này có thể tránh được rủi ro của chỉ số siêu xu hướng và ngăn ngừa tổn thất quá lớn.
Những ưu điểm chính của chiến lược này là:
Có thể ngăn ngừa hiệu quả rủi ro của chỉ số vượt quá xu hướng. Chỉ số vượt quá xu hướng tự nó không có khả năng tránh thiệt hại hiệu quả, giao dịch đường cong ròng có thể bù đắp cho thiếu sót này.
Khi giao dịch không thuận lợi, bạn có thể tạm ngưng giao dịch theo chiến lược để tránh thua lỗ quá lớn. Chờ cho đến khi thị trường chuyển hướng có thể mở lại.
Có thể tự động quản lý vị trí, không cần sự can thiệp của con người. Nó tự động tạm dừng khi đường cong giá trị ròng thấp hơn đường cong giá trị ròng và tự động mở khi đường cong giá trị ròng cao hơn đường cong giá trị ròng
Chiến lược này cũng có một số rủi ro:
Các tham số đặt sai có thể dẫn đến việc không thể sử dụng hiệu quả các giao dịch trên đường cong giá trị ròng. Cần chọn chu kỳ trung bình di chuyển thích hợp.
Khi xu hướng thị trường thay đổi, có thể không thể điều chỉnh vị trí kịp thời. Điều này sẽ dẫn đến một số tổn thất.
Vì phải chờ đợi đường cong giá trị ròng tăng trở lại, có thể sẽ bỏ lỡ cơ hội tốt nhất để tham gia.
Phản ứng:
Tối ưu hóa tham số, chọn chu kỳ trung bình di chuyển tốt nhất.
Các chỉ số khác được kết hợp với xu hướng đánh giá, điều chỉnh vị trí kịp thời.
Giảm thời gian tạm ngưng giao dịch để giảm khả năng bỏ lỡ.
Chính sách này có thể được tối ưu hóa theo các khía cạnh sau:
Kiểm tra các kết hợp tham số khác nhau để tìm ra chu kỳ ATR và ATR nhân tốt nhất.
Hãy thử các loại trung bình di chuyển khác, chẳng hạn như trung bình di chuyển chỉ số, trung bình di chuyển Hull.
Thêm các chỉ số khác để đánh giá xu hướng thị trường và điều chỉnh vị trí khi xu hướng thay đổi.
Tối ưu hóa chu kỳ trung bình di chuyển, tìm điểm cân bằng tốt nhất. Chu kỳ quá dài sẽ bỏ lỡ cơ hội, quá ngắn sẽ bị tạm dừng thường xuyên.
Tối ưu hóa các điều kiện tạm dừng giao dịch, chẳng hạn như thiết lập đường dừng lỗ, chỉ tạm dừng khi lỗ đạt đến một mức độ nhất định.
Chiến lược này kết hợp một cách khéo léo các chỉ số siêu xu hướng và giao dịch theo đường cong ròng. Nó giữ lại lợi thế của các chỉ số siêu xu hướng trong việc xác định xu hướng và kiểm soát rủi ro một cách hiệu quả thông qua giao dịch theo đường cong ròng. Kết quả thử nghiệm cho thấy trong hầu hết các trường hợp, việc sử dụng giao dịch theo đường cong ròng sẽ làm giảm lợi nhuận.
/*backtest
start: 2023-01-14 00:00:00
end: 2024-01-14 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
strategy('Supertrend & Equity curve with EMA', overlay=false, format=format.price, precision=2, initial_capital=100000)
eqlen = input.int(25, "EQ EMA len", group = "New Equity Curve Settings")
shEQandMA = input.bool(true, "Show Original Equity Curve and MA")
shEQfilt = input.bool(true, "Show Filtered Equity Curve by MA")
Periods = input(title='ATR Period', defval=10, group = "SuperTrend Settings")
src = input(hl2, title='Source', group = "SuperTrend Settings")
Multiplier = input.float(title='ATR Multiplier', step=0.1, defval=3.0, group = "SuperTrend Settings")
changeATR = input(title='Change ATR Calculation Method ?', defval=true, group = "SuperTrend Settings")
//SuperTrend Code
atr2 = ta.sma(ta.tr, Periods)
atr = changeATR ? ta.atr(Periods) : atr2
up = src - Multiplier * atr
up1 = nz(up[1], up)
up := close[1] > up1 ? math.max(up, up1) : up
dn = src + Multiplier * atr
dn1 = nz(dn[1], dn)
dn := close[1] < dn1 ? math.min(dn, dn1) : dn
trend = 1
trend := nz(trend[1], trend)
trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend
// Strategy main code
buySignal = trend == 1 and trend[1] == -1
sellSignal = trend == -1 and trend[1] == 1
if buySignal
strategy.entry('Long', strategy.long)
if sellSignal
strategy.entry('Short', strategy.short)
//Equity Curve calcs
eq = strategy.netprofit
ch = ta.change(eq)
neq = ch != 0 ? eq : na
mova = ta.ema(neq,eqlen)
// New Equity Curve
var float neweq = 0
var int ttrades = 0
var int wintrades = 0
var int losetrades = 0
switch
strategy.netprofit == strategy.netprofit[1] => na
strategy.netprofit < mova and strategy.netprofit[1] > mova => neweq := neweq + ch
strategy.netprofit < mova and strategy.netprofit[1] < mova => na
strategy.netprofit > mova and strategy.netprofit[1] > mova => neweq := neweq + ch
newch = ta.change(neweq)
switch
newch == 0 => na
newch > 0 =>
wintrades := wintrades +1
ttrades := ttrades +1
newch < 0 =>
losetrades := losetrades +1
ttrades := ttrades +1
//plot(eq, linewidth = 2)
//plot(mova, color=color.red)
//plot(neweq, color= color.green, linewidth = 3)
//Table
var testTable = table.new(position = position.top_right, columns = 5, rows = 10, bgcolor = color.green, border_width = 1)
table.cell(table_id = testTable, column = 0, row = 0, text = "Strategy: ", bgcolor=color.white)
table.cell(table_id = testTable, column = 1, row = 0, text = "Original: ", bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 0, text = "Equity Curve EMA: ", bgcolor=color.white)
table.cell(table_id = testTable, column = 0, row = 1, text = "Total Trades: ", bgcolor=color.white)
table.cell(table_id = testTable, column = 0, row = 2, text = "Win Trades: ", bgcolor=color.white)
table.cell(table_id = testTable, column = 0, row = 3, text = "Lose Trades: ", bgcolor=color.white)
table.cell(table_id = testTable, column = 0, row = 4, text = "Win Rate: ", bgcolor=color.white)
table.cell(table_id = testTable, column = 0, row = 5, text = "Net Profit: ", bgcolor=color.white)
//Equity Curve EMA stat
table.cell(table_id = testTable, column = 2, row = 1, text = str.tostring(ttrades), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 2, text = str.tostring(wintrades), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 3, text = str.tostring(losetrades), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 4, text = str.tostring(math.round(100*wintrades/ttrades,2)), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 5, text = str.tostring(math.round(neweq)), bgcolor=color.white)
//Original Strategy stat
// table.cell(table_id = testTable, column = 1, row = 1, text = str.tostring(strategy.closedtrades), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 2, text = str.tostring(strategy.wintrades), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 3, text = str.tostring(strategy.losstrades), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 4, text = str.tostring(math.round(100*strategy.wintrades/strategy.closedtrades,2)), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 5, text = str.tostring(math.round(strategy.netprofit)), bgcolor=color.white)
//New Equity curve
var newcurve = array.new_float(0)
var int ida = 0
var bool printEQ = false
if newch !=0
array.push(newcurve, neweq)
if bar_index > last_bar_index - array.size(newcurve) - 1 - 20 and array.size(newcurve) > 20
printEQ := true
else
printEQ := false
plot(printEQ and ida < strategy.closedtrades and shEQfilt ? array.get(newcurve, ida) : na, color=color.green, linewidth = 2)
if printEQ
ida := ida + 1
if ida >= array.size(newcurve) and printEQ
ida := array.size(newcurve) -1
//Original Equity curve
var newcurve2 = array.new_float(0)
var int ida2 = 0
var bool printEQ2 = false
if ch !=0
array.push(newcurve2, eq)
if bar_index > last_bar_index - array.size(newcurve2) - 1 - 20 and array.size(newcurve2) > 20
printEQ2 := true
else
printEQ2 := false
plot(printEQ2 and ida2 < strategy.closedtrades and shEQandMA ? array.get(newcurve2, ida2) : na, color=color.blue, linewidth = 2)
if printEQ2
ida2 := ida2 + 1
if ida2 >= array.size(newcurve2) and printEQ2
ida2 := array.size(newcurve2) -1
//Moving Average Array
var marray = array.new_float(0)
if ch
array.push(marray, mova)
plot(printEQ2 and array.size(marray) > 40 and shEQandMA ? array.get(marray, ida2-1) : na, color=color.red, linewidth = 1)
hline(0,"0 line", color=color.black, linestyle = hline.style_dotted)
if (last_bar_index-1) and array.size(newcurve2) > 20 and array.size(newcurve) > 20
l = label.new(bar_index+2, array.get(newcurve2, array.size(newcurve2)-1), "Original Equity Curve", color=color.rgb(33, 149, 243, 85), textcolor = color.black, style = label.style_label_left)
label.delete(l[1])
f = label.new(bar_index+2, array.get(newcurve, array.size(newcurve)-1), "Filtered Equity Curve", color=color.rgb(69, 238, 97, 85), textcolor = color.black, style = label.style_label_left)
label.delete(f[1])