Chiến lược giao dịch hai chiều đột phá động lượng


Ngày tạo: 2023-10-27 17:04:48 sửa đổi lần cuối: 2023-10-27 17:04:48
sao chép: 0 Số nhấp chuột: 655
1
tập trung vào
1617
Người theo dõi

Chiến lược giao dịch hai chiều đột phá động lượng

Tổng quan

Chiến lược này sử dụng đường trung bình di chuyển đơn giản để xác định xu hướng, làm nhiều hơn trong trường hợp tăng liên tục, làm giảm trong trường hợp giảm liên tục, thực hiện giao dịch hai chiều.

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

Chiến lược này sử dụng VWMA trung bình chuyển động trọng lượng để xác định xu hướng thị trường. Khi VWMA tăng, làm nhiều hơn; Khi VWMA giảm, làm ít hơn.

Cụ thể, chiến lược này đầu tiên tính toán VWMA của một chu kỳ nhất định, sau đó đánh giá xem VWMA có tăng hơn 5 ngày hay không, và nếu có, hãy mở nhiều vị trí; Nếu VWMA giảm hơn 5 ngày, hãy mở vị trí và đóng cửa. Điều kiện để đóng cửa là VWMA hướng đảo ngược sau hơn 5 ngày.

Để tính toán hiệu suất thu nhập hàng tháng và hàng năm, chiến lược ghi lại thu nhập hàng tháng và hàng năm. Bằng cách so sánh chiến lược này với thu nhập chuẩn của thị trường, bạn có thể trực quan thấy hiệu suất của chiến lược đối với thị trường.

Phân tích lợi thế

Chiến lược này có những ưu điểm sau:

  1. Sử dụng VWMA để đánh giá xu hướng, bạn có thể lọc hiệu quả tiếng ồn thị trường và nắm bắt các xu hướng chính.

  2. Chỉ mở đầu tư khi có xu hướng mới có thể tránh được rủi ro của sự đảo ngược xu hướng.

  3. Với giao dịch hai chiều, bạn có thể kiếm được lợi nhuận bất kể thị trường tăng hay giảm.

  4. Ghi lại thu nhập hàng tháng và hàng năm để đánh giá hiệu quả của chiến lược.

  5. Thêm lợi nhuận chuẩn thị trường vào bảng thu nhập, bạn có thể trực quan so sánh chiến lược với hiệu suất tương đối của thị trường.

Phân tích rủi ro

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

  1. Sử dụng VWMA để đánh giá xu hướng có thể bị trì trệ, có thể bỏ lỡ cơ hội trong giai đoạn bắt đầu của xu hướng.

  2. Nếu bạn chỉ mở lệnh khi xu hướng được xác nhận, bạn có thể sẽ bỏ lỡ một phần của Movement.

  3. Giao dịch hai chiều cần xác định điểm dừng lỗ, nếu không, tổn thất có thể tăng lên.

  4. Sự biến động của thị trường lớn có thể dẫn đến việc dừng lỗ được kích hoạt, không thể giữ xu hướng hoàn chỉnh.

  5. Sự thay đổi này có thể không chính xác, dẫn đến tổn thất lớn hơn.

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

Chính sách này có thể được tối ưu hóa bằng cách:

  1. Tối ưu hóa tham số chu kỳ VWMA, cải thiện phán đoán xu hướng.

  2. Điều chỉnh số ngày xác nhận xu hướng, cải thiện thời gian ra sân.

  3. Thêm chiến lược dừng lỗ để kiểm soát tổn thất đơn lẻ.

  4. Kết hợp với các chỉ số khác để đánh giá xu hướng đảo ngược, tăng độ chắc chắn.

  5. Tối ưu hóa quản lý vị trí, điều chỉnh vị trí theo thị trường.

  6. Xét chi phí giao dịch, đặt lợi nhuận tối thiểu.

Tóm tắt

Chiến lược này có ý tưởng tổng thể rõ ràng và đơn giản, sử dụng VWMA để đánh giá xu hướng xu hướng, giao dịch hai chiều sau khi xác nhận xu hướng, có thể theo dõi thị trường một cách hiệu quả. Tuy nhiên, cũng có một số rủi ro, cần kiểm tra và tối ưu hóa các tham số hơn nữa, điều chỉnh logic ra ngoài và kiểm soát kích thước vị trí thích hợp. Chiến lược này dựa trên chiến lược giao dịch hai chiều, đặt nền tảng cho giao dịch định lượng, đáng để nghiên cứu và cải tiến thêm.

Mã nguồn chiến lược
/*backtest
start: 2023-01-01 00:00:00
end: 2023-10-26 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy(title="Monthly Returns in Strategies with Market Benchmark", shorttitle="Monthly P&L With Market", 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")//

///////////////////
// MONTHLY TABLE //

new_month = month(time) != month(time[1])
new_year  = year(time)  != year(time[1])

eq = strategy.equity

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

cur_month_pnl = 0.0
cur_year_pnl  = 0.0
cur_month_bh = 0.0
cur_year_bh  = 0.0

// Current Monthly P&L
cur_month_pnl := new_month ? 0.0 : 
                 (1 + cur_month_pnl[1]) * (1 + bar_pnl) - 1 
cur_month_bh := new_month ? 0.0 : 
                 (1 + cur_month_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 Monthly P&Ls
var month_pnl  = array.new_float(0)
var month_time = array.new_int(0)
var month_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)

last_computed = false

if (not na(cur_month_pnl[1]) and (new_month or time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory))
    if (last_computed[1])
        array.pop(month_pnl)
        array.pop(month_time)
        
    array.push(month_pnl , cur_month_pnl[1])
    array.push(month_time, time[1])
    array.push(month_bh , cur_month_bh[1])

if (not na(cur_year_pnl[1]) and (new_year or time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory))
    if (last_computed[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])

last_computed := (time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory) ? true : nz(last_computed[1])

// Monthly P&L Table    
var monthly_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
            color.new(color.red, transp = 20)
        else if pnl < bh
            color.new(color.red, transp = 50)
        else
            color.new(color.red, transp = 80)

if last_computed
    monthly_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)

    table.cell(monthly_table, 0,  0, "",     bgcolor = #cccccc)
    table.cell(monthly_table, 1,  0, "Jan",  bgcolor = #cccccc)
    table.cell(monthly_table, 2,  0, "Feb",  bgcolor = #cccccc)
    table.cell(monthly_table, 3,  0, "Mar",  bgcolor = #cccccc)
    table.cell(monthly_table, 4,  0, "Apr",  bgcolor = #cccccc)
    table.cell(monthly_table, 5,  0, "May",  bgcolor = #cccccc)
    table.cell(monthly_table, 6,  0, "Jun",  bgcolor = #cccccc)
    table.cell(monthly_table, 7,  0, "Jul",  bgcolor = #cccccc)
    table.cell(monthly_table, 8,  0, "Aug",  bgcolor = #cccccc)
    table.cell(monthly_table, 9,  0, "Sep",  bgcolor = #cccccc)
    table.cell(monthly_table, 10, 0, "Oct",  bgcolor = #cccccc)
    table.cell(monthly_table, 11, 0, "Nov",  bgcolor = #cccccc)
    table.cell(monthly_table, 12, 0, "Dec",  bgcolor = #cccccc)
    table.cell(monthly_table, 13, 0, "Year", bgcolor = #999999)


    for yi = 0 to array.size(year_pnl) - 1
        table.cell(monthly_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(monthly_table, 13, yi + 1, tostring(round(array.get(year_pnl, yi) * 100)) + " (" + tostring(round(array.get(year_bh, yi) * 100)) + ")", bgcolor = y_color)
        
    for mi = 0 to array.size(month_time) - 1
        m_row   = year(array.get(month_time, mi))  - year(array.get(year_time, 0)) + 1
        m_col   = month(array.get(month_time, mi)) 
        m_color = getCellColor(array.get(month_pnl, mi), array.get(month_bh, mi))
        
        table.cell(monthly_table, m_col, m_row, tostring(round(array.get(month_pnl, mi) * 100)) + " (" + tostring(round(array.get(month_bh, mi) * 100)) +")", bgcolor = m_color)