Chiến lược giao dịch xu hướng dựa trên đường trung bình động

Tác giả:ChaoZhang, Ngày: 2023-10-30 15:53:25
Tags:

img

Tổng quan

Chiến lược này sử dụng một hệ thống trung bình động để xác định hướng xu hướng hiện tại và thực hiện các vị trí dài hoặc ngắn theo xu hướng. Khi trung bình động tăng, độ tin cậy trong dài cao hơn, vì vậy đi dài. Khi trung bình động giảm, độ tin cậy trong ngắn cao hơn, vì vậy đi ngắn. Chiến lược này chủ yếu sử dụng hệ thống trung bình động để xác định hướng xu hướng thị trường, thuộc về chiến lược theo xu hướng.

Chiến lược logic

  1. Tính toán trung bình động vwma được cân nhắc như chỉ số trung bình động trong một khoảng thời gian nhất định (định dạng 400 khoảng thời gian).

  2. Xác định xem trung bình động vwma đang tăng, nếu tăng đặt tín hiệu dài xu hướng tăng; nếu giảm đặt tín hiệu ngắn xu hướng giảm.

  3. Khi xu hướng tăng là đúng, đi dài; khi xu hướng giảm là đúng, đóng dài và đi ngắn.

  4. Tính toán chiến lược return bar_pnl và buy & hold return bar_bh cho mỗi thanh.

  5. Theo các dấu thời gian hàng quý và hàng năm, tính toán lợi nhuận chiến lược hàng quý_pnl, lợi nhuận hàng năm_pnl và lợi nhuận mua & giữ tương ứng quý_bh, năm_bh.

  6. Hiển thị lợi nhuận chiến lược hàng quý so với lợi nhuận mua & giữ trong một bảng.

Phân tích lợi thế

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

  1. Định hướng thị trường bằng đường trung bình động, dễ hiểu.

  2. Có khả năng kiểm soát việc rút tiền, theo xu hướng sẽ giảm lỗ ở các thị trường không có xu hướng.

  3. Một số tham số có thể điều chỉnh, chủ yếu là điều chỉnh thời gian trung bình động, dễ kiểm tra và tối ưu hóa.

  4. Bảng trả về trực quan để hiển thị kết quả rõ ràng.

  5. Thêm buy & hold return trong bảng để so sánh, cho thấy lợi nhuận dư thừa.

  6. Vị trí bàn linh hoạt, dễ dàng tích hợp với các chiến lược khác.

Phân tích rủi ro

Ngoài ra còn có một số rủi ro:

  1. Hiệu suất thấp trong thị trường bò lâu dài so với mua & giữ.

  2. Có thể thêm các điều kiện lọc như phá vỡ mức cao trước đó để giảm giao dịch.

  3. Trung bình động có khả năng phù hợp đường cong kém, có thể bỏ lỡ các điểm chuyển hướng. Có thể kiểm tra các loại trung bình động khác nhau.

  4. Không có cơ chế dừng lỗ, rủi ro rút tiền lớn.

  5. Đối với bảng, có thể thêm các chỉ số rủi ro như tỷ lệ sắc nét, rút tối đa.

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

Chiến lược có thể được tối ưu hóa trong các khía cạnh sau:

  1. Tối ưu hóa các thông số trung bình động, điều chỉnh thời gian dựa trên chế độ thị trường.

  2. Thêm các bộ lọc như phá vỡ mức cao trước để giảm các chém.

  3. Hãy thử các loại trung bình động khác nhau, như WMA, DEMA v.v.

  4. Thêm các cơ chế dừng lỗ, như dừng động hoặc kích thước vị trí.

  5. Làm giàu nội dung của bảng, thêm các số liệu như tỷ lệ sắc nét, rút tối đa.

  6. Kết hợp với các chỉ số khác như MACD, Bollinger Bands để xác định xu hướng.

  7. Tối ưu hóa kích thước vị trí, điều chỉnh vị trí năng động dựa trên điều kiện thị trường.

  8. Thử nghiệm trên các sản phẩm khác nhau, tìm phạm vi ứng dụng tốt nhất.

Kết luận

Chiến lược giao dịch trung bình động là tương đối đơn giản và đơn giản. Nó theo xu hướng bằng cách xác định xu hướng bằng cách sử dụng trung bình động, với kiểm soát rút tiền tốt, phù hợp với các nhà giao dịch theo xu hướng. Vẫn còn nhiều chỗ để tối ưu hóa, như hệ thống trung bình động, cơ chế dừng lỗ, kích thước vị trí vv để làm cho nó thích nghi với môi trường thị trường phức tạp. Thiết kế bảng so sánh chiến lược trả về mua & giữ, hiển thị lợi nhuận dư thừa trực quan. Khung và thiết kế bảng của chiến lược này có thể cung cấp một số tham chiếu tốt cho các nhà giao dịch định lượng.


/*backtest
start: 2022-10-23 00:00:00
end: 2023-10-29 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Dannnnnnny

//@version=4
strategy(title="Quarterly Returns in Strategies vs Buy & Hold", initial_capital= 1000, overlay=true,default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, commission_value = 0.1)
maLength= input(400)

wma= vwma(hl2,maLength)
uptrend= rising(wma, 5)
downtrend= falling(wma,5)

plot(wma)

if uptrend
    strategy.entry("Buy", strategy.long)
else
    strategy.close("Buy")//

///////////////////
// QUARTERLY TABLE //
enableQuarterlyTable = input(title="Enable Quarterly Return table", type=input.bool, defval=false)
enableCompareWithMarket = input(title="Compare with Market Benchmark", type=input.bool, defval=false)
table_position = input(title="Table Position", type=input.string, defval='bottom_right', options=['bottom_right','bottom_left','top_right', 'top_left'])
precision = 2
new_quarter = ceil(month(time)/3)  != ceil(month(time[1])/3)
new_year  = year(time)  != year(time[1])

eq = strategy.equity

bar_pnl = eq / eq[1] - 1
bar_bh = (close-close[1])/close[1]

cur_quarter_pnl = 0.0
cur_year_pnl  = 0.0
cur_quarter_bh = 0.0
cur_year_bh  = 0.0

// Current Quarterly P&L
cur_quarter_pnl := new_quarter ? 0.0 : 
                 (1 + cur_quarter_pnl[1]) * (1 + bar_pnl) - 1 
cur_quarter_bh := new_quarter ? 0.0 : 
                 (1 + cur_quarter_bh[1]) * (1 + bar_bh) - 1

// Current Yearly P&L
cur_year_pnl := new_year ? 0.0 : 
                 (1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1
cur_year_bh := new_year ? 0.0 : 
                 (1 + cur_year_bh[1]) * (1 + bar_bh) - 1

// Arrays to store Yearly and Quarterly P&Ls
var quarter_pnl  = array.new_float(0)
var quarter_time = array.new_int(0)
var quarter_bh  = array.new_float(0)

var year_pnl  = array.new_float(0)
var year_time = array.new_int(0)
var year_bh  = array.new_float(0)

end_time = false

end_time:= time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory

if (not na(cur_quarter_pnl[1]) and (new_quarter or end_time))
    if (end_time[1])
        array.pop(quarter_pnl)
        array.pop(quarter_time)
        
    array.push(quarter_pnl , cur_quarter_pnl[1])
    array.push(quarter_time, time[1])
    array.push(quarter_bh , cur_quarter_bh[1])

if (not na(cur_year_pnl[1]) and (new_year or end_time))
    if (end_time[1])
        array.pop(year_pnl)
        array.pop(year_time)
        
    array.push(year_pnl , cur_year_pnl[1])
    array.push(year_time, time[1])
    array.push(year_bh , cur_year_bh[1])

// Quarterly P&L Table    
var quarterly_table = table(na)

getCellColor(pnl, bh)  => 
    if pnl > 0
        if bh < 0 or pnl > 2 * bh
            color.new(color.green, transp = 20)
        else if pnl > bh
            color.new(color.green, transp = 50)
        else
            color.new(color.green, transp = 80)
    else
        if bh > 0 or pnl < 2 * bh
            color.new(color.red, transp = 20)
        else if pnl < bh
            color.new(color.red, transp = 50)
        else
            color.new(color.red, transp = 80)

if (end_time and enableQuarterlyTable)
    quarterly_table := table.new(table_position, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)

    table.cell(quarterly_table, 0,  0, "",     bgcolor = #cccccc)
    table.cell(quarterly_table, 1,  0, "Q1",  bgcolor = #cccccc)
    table.cell(quarterly_table, 2,  0, "Q2",  bgcolor = #cccccc)
    table.cell(quarterly_table, 3,  0, "Q3",  bgcolor = #cccccc)
    table.cell(quarterly_table, 4,  0, "Q4",  bgcolor = #cccccc)
    table.cell(quarterly_table, 5,  0, "Year", bgcolor = #999999)


    for yi = 0 to array.size(year_pnl) - 1
        table.cell(quarterly_table, 0,  yi + 1, tostring(year(array.get(year_time, yi))), bgcolor = #cccccc)
        
        y_color = getCellColor(array.get(year_pnl, yi), array.get(year_bh, yi))
        table.cell(quarterly_table, 5, yi + 1, enableCompareWithMarket ? tostring(round(array.get(year_pnl, yi) * 100, precision)) + " (" + tostring(round(array.get(year_bh, yi) * 100, precision)) + ")" : tostring(round(array.get(year_pnl, yi) * 100, precision)), bgcolor = y_color, text_color=#bfbfbf)
        
    for mi = 0 to array.size(quarter_time) - 1
        m_row   = year(array.get(quarter_time, mi))  - year(array.get(year_time, 0)) + 1
        m_col   = ceil(month(array.get(quarter_time, mi)) / 3)
        m_color = getCellColor(array.get(quarter_pnl, mi), array.get(quarter_bh, mi))
        
        table.cell(quarterly_table, m_col, m_row, enableCompareWithMarket ?  tostring(round(array.get(quarter_pnl, mi) * 100, precision)) + " (" + tostring(round(array.get(quarter_bh, mi) * 100,precision)) +")" : tostring(round(array.get(quarter_pnl, mi) * 100, precision)), bgcolor = m_color, text_color=#bfbfbf)

Thêm nữa