Chiến lược giao dịch định lượng dựa trên chỉ số siêu xu hướng và giao dịch đường cong cổ phần

Tác giả:ChaoZhang, Ngày: 2024-01-15 11:41:53
Tags:

img

Tổng quan

Ý tưởng cốt lõi của chiến lược này là kết hợp chỉ số Supertrend với giao dịch đường cong cổ phiếu. Khi chỉ số Supertrend tạo 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. Thay vào đó, chúng tôi kiểm tra xem đường cong cổ phiếu hiện tại có dưới mức trung bình động không. Chúng tôi sẽ chỉ mở các vị trí khi đường cong cổ phiếu trên mức trung bình động. Khi đường cong cổ phiếu dưới mức trung bình động, chúng tôi sẽ tạm dừng giao dịch cho chiến lược hiện tại. Điều này có thể ngăn chặn việc mở rộng lỗ hiệu quả.

Chiến lược logic

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

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

Công thức tính toán cho chỉ số Supertrend là:

Phạm vi trên = Giá nguồn - ATR Multiplier * ATR Phạm vi thấp hơn = Giá nguồn + ATR Multiplier * ATR

Trong đó ATR là viết tắt của Average True Range. Chỉ số Supertrend sử dụng ATR để thiết lập các dải trên và dưới. Một đột phá trên dải trên là tín hiệu bán, trong khi một đột phá dưới dải dưới là tín hiệu mua.

Ý tưởng đằng sau giao dịch đường cong cổ phiếu là chúng ta lấy đường trung bình động của đường cong cổ phiếu của chiến lược. Khi đường cong cổ phiếu giảm xuống dưới đường trung bình động của nó, chúng ta tạm dừng giao dịch cho chiến lược hiện tại và chờ đường cong cổ phiếu phục hồi trở lại trên đường trung bình động trước khi kích hoạt lại giao dịch.

Chiến lược này kết hợp cả hai kỹ thuật, do đó sau khi chỉ số Supertrend tạo ra tín hiệu giao dịch, chúng ta không trực tiếp tham gia giao dịch. Thay vào đó, chúng ta kiểm tra xem đường cong vốn chủ sở hữu hiện tại có cao hơn trung bình động của nó không. Chỉ khi cả hai điều kiện được đáp ứng, chúng ta sẽ mở các vị trí. Điều này có thể giảm thiểu hiệu quả các rủi ro vốn có trong chỉ số Supertrend và ngăn ngừa thua lỗ quá mức.

Ưu điểm

Những lợi thế chính của chiến lược này là:

  1. Nó có thể ngăn chặn hiệu quả các rủi ro của chỉ số Supertrend. Chỉ số Supertrend không thể ngăn chặn thua lỗ hiệu quả. Giao dịch đường cong cổ phiếu bù đắp cho sự thiếu sót này.

  2. Khi giao dịch trở nên không thuận lợi, nó tạm dừng giao dịch để tránh tổn thất quá mức. Chúng tôi có thể tiếp tục giao dịch sau khi thị trường phục hồi.

  3. Nó có thể tự động quản lý các vị trí mà không cần can thiệp bằng tay. Giao dịch được tạm dừng tự động khi đường cong cổ phiếu giảm xuống dưới đường trung bình động, và tiếp tục khi đường cong cổ phiếu bật trở lại trên nó.

Rủi ro

Ngoài ra còn có một số rủi ro với chiến lược này:

  1. Các thiết lập tham số không chính xác có thể làm cho giao dịch đường cong cổ phiếu không hiệu quả.

  2. Nó có thể không điều chỉnh các vị trí ngay lập tức khi xu hướng thị trường thay đổi.

  3. Nó có thể bỏ lỡ những cơ hội giao dịch tốt trong khi chờ đợi đường cong cổ phiếu phục hồi.

Các biện pháp đối phó:

  1. Tối ưu hóa các tham số và chọn thời gian trung bình động tốt nhất.

  2. Kết hợp các chỉ số khác để đánh giá xu hướng và điều chỉnh các vị trí phù hợp.

  3. Giảm thời gian ngừng giao dịch để giảm khả năng bỏ lỡ cơ hội.

Hướng dẫn tối ưu hóa

Chúng ta có thể tối ưu hóa chiến lược từ 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 thời gian ATR tối ưu và nhân.

  2. Hãy thử các loại trung bình di chuyển khác, như trung bình di chuyển biểu thức, trung bình di chuyển Hull vv

  3. Thêm các chỉ số khác để xác định xu hướng thị trường và điều chỉnh các vị trí khi xu hướng thay đổi.

  4. Tối ưu hóa thời gian trung bình động để tìm sự cân bằng tốt nhất.

  5. Tối ưu hóa các điều kiện để tạm dừng giao dịch, như đặt ngưỡng dừng lỗ trước khi đình chỉ.

Kết luận

Chiến lược này kết hợp thông minh chỉ số Supertrend với giao dịch đường cong cổ phiếu, tận dụng điểm mạnh của cả hai kỹ thuật. Kết quả thử nghiệm cho thấy trong hầu hết các trường hợp, áp dụng giao dịch đường cong cổ phiếu thực sự làm giảm lợi nhuận. Như vậy, chiến lược này phù hợp hơn cho các nhà giao dịch phòng thủ. Với tối ưu hóa tham số và logic, nó có thể trở thành một chiến lược giao dịch định lượng rất thực tế.


/*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])

Thêm nữa