Chiến lược định lượng dựa trên chỉ báo xu hướng siêu và giao dịch đường cong vốn chủ sở hữu


Ngày tạo: 2024-01-15 11:41:53 sửa đổi lần cuối: 2024-01-15 11:41:53
sao chép: 1 Số nhấp chuột: 601
1
tập trung vào
1617
Người theo dõi

Chiến lược định lượng dựa trên chỉ báo xu hướng siêu và giao dịch đường cong vốn chủ sở hữu

Tổng quan

Ý 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.

Nguyên tắc chiến lược

Chiến lược này bao gồm hai phần chính:

  1. Chỉ số siêu xu hướng
  2. Giao dịch đường cong

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.

Phân tích lợi thế

Những ưu điểm chính của chiến lược này là:

  1. 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.

  2. 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.

  3. 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

Phân tích rủi ro

Chiến lược này cũng có một số rủi ro:

  1. 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.

  2. 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.

  3. 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:

  1. Tối ưu hóa tham số, chọn chu kỳ trung bình di chuyển tốt nhất.

  2. 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.

  3. Giảm thời gian tạm ngưng giao dịch để giảm khả năng bỏ lỡ.

Hướng tối ưu hóa

Chính sách này có thể được tối ưu hóa theo các khía cạnh sau:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

Tóm tắt

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.

Mã nguồn chiến lược
/*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])