Chiến lược giao dịch ETF dựa trên ATR và Breakout

Tác giả:ChaoZhang, Ngày: 2023-12-26 16:05:55
Tags:

img

Tổng quan

Đây là một chiến lược giao dịch thuật toán ETF dựa trên Average True Range (ATR) và price breakout. Nó sử dụng ATR để tính toán mức dừng lỗ và lấy lợi nhuận, và mở các vị trí dài hoặc ngắn khi giá vượt qua mức giá cao nhất hoặc thấp nhất trong một khoảng thời gian nhất định.

Chiến lược logic

Chiến lược này chủ yếu dựa trên các nguyên tắc sau:

  1. Sử dụng giá cao nhất và thấp nhất trong một khoảng thời gian nhất định (ví dụ: 20 nến) để xác định xu hướng và hướng giá.

  2. Sử dụng ATR để tính toán mức dừng lỗ một cách năng động. Stop loss được đặt ở khoảng cách của giá trị ATR của một khoảng thời gian ATR nhân với một hệ số (ví dụ 2) từ giá nhập cảnh.

  3. Sử dụng ATR để xác định mức lợi nhuận. Lợi nhuận được đặt ở khoảng cách của giá trị ATR của một khoảng thời gian ATR nhân một hệ số (ví dụ 1) từ giá nhập cảnh.

  4. Sử dụng ATR trailer multiplier để theo dõi stop loss. Đóng các vị trí với stop loss khi giá vượt qua mức stop loss trailer theo hướng không thuận lợi.

Chiến lược đơn giản và đáng tin cậy, vì nó xem xét cả hướng xu hướng giá để bắt kịp thời các biến động giá, và thiết lập dừng lỗ và lấy lợi nhuận để lấy lợi nhuận và kiểm soát rủi ro.

Phân tích lợi thế

Những lợi thế của chiến lược này bao gồm:

  1. Logic chiến lược đơn giản và rõ ràng, dễ hiểu và thực hiện.

  2. Sử dụng ATR để tính toán mức dừng lỗ thích nghi và lấy lợi nhuận giúp kích thước vị trí linh hoạt và kiểm soát rủi ro.

  3. Chiến lược đột phá là tốt trong việc bắt được xu hướng giá, dẫn đến lợi nhuận tốt.

  4. Lỗ dừng xe kéo có thể đóng các vị trí kịp thời, tránh mất quá mức.

  5. Nó phù hợp với các sản phẩm có xu hướng rõ ràng, như ETF và cổ phiếu.

Phân tích rủi ro

Các rủi ro của chiến lược bao gồm:

  1. Nhiều tín hiệu sai và mở ngược có thể xảy ra trong quá trình củng cố giá.

  2. Điều chỉnh tham số không đúng có thể dẫn đến xu hướng giá bị thiếu hoặc quá nhiều giao dịch không cần thiết.

  3. Các giá trị tham số cực đoan có thể dẫn đến stop loss quá hung hăng hoặc quá bảo thủ và lấy lợi nhuận, ảnh hưởng đến lợi nhuận chiến lược.

  4. Các rủi ro cơ bản của ETF như rủi ro chính sách và phí bảo hiểm cũng có thể ảnh hưởng đến hiệu suất chiến lược.

Các giải pháp tương ứng:

  1. Tối ưu hóa các thông số để giảm các giao dịch không cần thiết.
  2. Thêm thêm các yếu tố và bộ lọc để xác nhận tín hiệu giao dịch.
  3. Điều chỉnh các thông số thích nghi với các thị trường khác nhau.
  4. Phân phối kích thước đầu tư và vị trí kiểm soát của một ETF duy nhất.

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

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

  1. Thêm các chỉ số như trung bình động để lọc ra các tín hiệu sai.

  2. Phát triển mô-đun tối ưu hóa tham số thích nghi để tự động điều chỉnh các tham số cho các giai đoạn và sản phẩm khác nhau.

  3. Sử dụng các mô hình học máy để dự đoán giá cao nhất và thấp nhất của nến tiếp theo để xác định tín hiệu đột phá.

  4. Xem xét khối lượng giao dịch tràn ra để tránh phá vỡ sai.

  5. Tối ưu hóa kích thước vị trí ban đầu và tỷ lệ phân bổ phù hợp với các sản phẩm và chế độ thị trường khác nhau.

Kết luận

Chiến lược có logic rõ ràng và đơn giản. Các cơ chế cốt lõi của breakout và thích nghi ATR dừng lỗ / lấy lợi nhuận có thể kiểm soát hiệu quả rủi ro và khóa lợi nhuận. Tăng cường thêm các yếu tố lợi nhuận và khả năng kiểm soát rủi ro thông qua tối ưu hóa tham số và tích hợp nhiều bộ lọc có thể làm cho nó trở thành một chiến lược định lượng có lợi nhuận và tối ưu hóa.


/*backtest
start: 2023-12-18 00:00:00
end: 2023-12-21 03:00:00
period: 1m
basePeriod: 1m
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/
// © FX_minds

//@version=4
strategy("ETF tradedr", overlay=true, pyramiding=100, default_qty_type=strategy.percent_of_equity, default_qty_value=100)

//------------------------------ get user input
lookback                   = input(title="HH LL lookback", type=input.integer, defval=20)
ATR_periode                = input(title="ATR period", type=input.integer, defval=14)
ATR_SL_multiplier          = input(title="ATR SL multiplier", type=input.float, defval=2)
ATR_TP_multiplier          = input(title="ATR TP multiplier", type=input.float, defval=1)
trailing_SL_ATR_multiplier = input(title="ATR trailing SL multiplier", type=input.float, defval=3.5)
lookback_trailing_SL       = input(title="trailing SL lookback", type=input.integer, defval=4)
max_sequel_trades          = input(title="max sequel trades", type=input.float, defval=1)
trade_long                 = input(title= "trade long ?", type=input.bool, defval=true)
trade_short                = input(title= "trade short ?", type=input.bool, defval=false)

//------------------------------ determine entry conditions
long_condition   = barstate.isconfirmed and crossover(high, highest(high, lookback)[1])
short_condition  = barstate.isconfirmed and crossunder(low, lowest(low, lookback)[1])


//------------------------------ count open long trades
count_open_longs = 0
count_open_longs := nz(count_open_longs[1])

if (long_condition) 
    count_open_longs := count_open_longs +1
    //label.new(bar_index, low, tostring(count_open_longs, "#"), xloc.bar_index, yloc.belowbar, color.green, label.style_none, color.green, size.large)

if (short_condition)
    count_open_longs := 0


//------------------------------ count open short trades
count_open_shorts = 0
count_open_shorts := nz(count_open_shorts[1])

if (short_condition)
    count_open_shorts := count_open_shorts +1
    //label.new(bar_index, low, tostring(count_open_shorts, "#"), xloc.bar_index, yloc.belowbar, color.red, label.style_none, color.red, size.large)

if (long_condition)
    count_open_shorts := 0


//------------------------------ calculate entryprice
entryprice_long = long_condition ? close : na
entryprice_short = short_condition ? close : na


//------------------------------ calculate SL & TP
SL_distance = atr(ATR_periode) * ATR_SL_multiplier
TP_distance  = atr(ATR_periode) * ATR_TP_multiplier
trailing_SL_distance = atr(ATR_periode) * trailing_SL_ATR_multiplier

SL_long = entryprice_long - SL_distance
SL_short = entryprice_short + SL_distance

trailing_SL_short = lowest(close, lookback_trailing_SL) + trailing_SL_distance
trailing_SL_long  = highest(close, lookback_trailing_SL) - trailing_SL_distance

trailing_SL_short_signal = crossover(high, trailing_SL_short[1])
trailing_SL_long_signal = crossunder(low, trailing_SL_long[1])


//------------------------------ plot entry price & SL  
plot(entryprice_long, style=plot.style_linebr, color=color.white)
plot(SL_long, style=plot.style_linebr, color=color.red)
plot(SL_short, style=plot.style_linebr, color=color.green)
plot(trailing_SL_short, style=plot.style_linebr, color=color.red)
plot(trailing_SL_long, style=plot.style_linebr, color=color.green)


//------------------------------ submit entry orders
if (long_condition) and (count_open_longs <= max_sequel_trades) and (trade_long == true)
    strategy.entry("Long" + tostring(count_open_longs, "#"), strategy.long)
    strategy.exit("SL Long"+ tostring(count_open_longs, "#"), 
     from_entry="Long" + tostring(count_open_longs, "#"), stop=SL_long)

if (short_condition) and (count_open_shorts <= max_sequel_trades) and (trade_short == true)
    strategy.entry("Short" + tostring(count_open_shorts, "#"), strategy.short)
    strategy.exit("SL Short" + tostring(count_open_shorts, "#"), 
     from_entry="Short" + tostring(count_open_shorts, "#"), stop=SL_short)
    

//------------------------------ submit exit conditions
if (trailing_SL_long_signal)
    strategy.close("Long" + tostring(count_open_longs, "#"))
    strategy.close("Long" + tostring(count_open_longs-1, "#"))
    strategy.close("Long" + tostring(count_open_longs-2, "#"))
    strategy.close("Long" + tostring(count_open_longs-4, "#"))
    strategy.close("Long" + tostring(count_open_longs-5, "#"))
    strategy.close("Long" + tostring(count_open_longs-6, "#"))
    strategy.close("Long" + tostring(count_open_longs-7, "#"))
    strategy.close("Long" + tostring(count_open_longs-8, "#"))
    strategy.close("Long" + tostring(count_open_longs-9, "#"))
    
if (trailing_SL_short_signal)
    strategy.close("Short" + tostring(count_open_shorts, "#"))
    strategy.close("Short" + tostring(count_open_shorts-1, "#"))
    strategy.close("Short" + tostring(count_open_shorts-2, "#"))
    strategy.close("Short" + tostring(count_open_shorts-3, "#"))
    strategy.close("Short" + tostring(count_open_shorts-4, "#"))
    strategy.close("Short" + tostring(count_open_shorts-5, "#"))
    strategy.close("Short" + tostring(count_open_shorts-6, "#"))
    strategy.close("Short" + tostring(count_open_shorts-7, "#"))
    strategy.close("Short" + tostring(count_open_shorts-8, "#"))
    strategy.close("Short" + tostring(count_open_shorts-9, "#"))



Thêm nữa