Chiến lược theo xu hướng với đường trung bình động và siêu xu hướng

Tác giả:ChaoZhang, Ngày: 2023-10-20 16:50:01
Tags:

img

Tổng quan

Chiến lược này kết hợp các chỉ số Moving Average và chỉ số SuperTrend để thực hiện một chiến lược theo xu hướng với việc dừng lỗ. Nó tận dụng tối đa khả năng đánh giá xu hướng của Moving Averages và chức năng dừng lỗ của SuperTrend để theo dõi hiệu quả xu hướng và kiểm soát rủi ro.

Chiến lược logic

Chiến lược sử dụng hai trung bình động FRAMA cho tín hiệu giao dịch và chỉ số SuperTrend để lọc.

Đặc biệt, khi đường nhanh vượt qua đường chậm, một tín hiệu mua được tạo ra. Khi đường nhanh vượt qua đường chậm, một tín hiệu bán được tạo ra. Để tránh phá vỡ sai, chiến lược thêm một bộ lọc yêu cầu chỉ số SuperTrend phải thẳng hàng. Các giao dịch chỉ được thực hiện khi SuperTrend đồng ý với hướng tín hiệu.

Đối với quản lý vị trí, chiến lược sử dụng thay đổi hướng SuperTrend như một tín hiệu dừng lỗ.

Ngoài ra, việc dừng lỗ sau có thể được kích hoạt như một tùy chọn. Sau khi đạt được mục tiêu lợi nhuận nhất định, việc dừng lại sau có thể được sử dụng để khóa lợi nhuận.

Phân tích lợi thế

  • Sử dụng Moving Averages để xác định hướng xu hướng, có thể lọc ra tiếng ồn thị trường và đánh giá chính xác xu hướng
  • Kết hợp với bộ lọc SuperTrend tránh các giao dịch sai từ các vụ phá vỡ sai
  • Thay đổi hướng SuperTrend hoạt động như điểm dừng lỗ, cho phép dừng lỗ nhanh chóng và kiểm soát rủi ro hiệu quả
  • Tùy chọn dừng lỗ có thể tối đa hóa lợi nhuận

Phân tích rủi ro

  • Là một chiến lược theo xu hướng, nó dễ bị ảnh hưởng bởi các thị trường khác nhau.
  • Đường trung bình di chuyển có tác dụng chậm, có thể gây ra nhập cảnh sớm hoặc muộn
  • Các thông số SuperTrend không chính xác có thể dẫn đến stop loss quá hung hăng hoặc quá bảo thủ
  • Khi kích hoạt dừng kéo, chiều rộng kéo cần phải được thiết lập đúng cách để tránh mất dừng quá mức

Những rủi ro này có thể được giảm bằng cách điều chỉnh các thông số Moving Average, tối ưu hóa các cài đặt SuperTrend và sử dụng stop loss theo đúng cách.

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 tham số Moving Average để tìm kết hợp tham số tốt nhất

Các kết hợp thời gian khác nhau có thể được thử nghiệm để tìm sự cân bằng tối ưu giữa độ mịn và độ nhạy.

  1. Tùy chỉnh tham số SuperTrend

Các khoảng thời gian ATR và nhân khác nhau có thể được thử nghiệm để tối ưu hóa hiệu ứng dừng lỗ.

  1. Thêm các bộ lọc chỉ số khác

Các bộ lọc bổ sung như kênh Donchian, chỉ số biến động có thể được thử nghiệm.

  1. Tối ưu hóa các thông số dừng kéo theo

Có thể thử nghiệm các chiều rộng khác nhau để tối đa hóa lợi nhuận và kiểm soát rủi ro.

  1. Kết hợp với các chiến lược dừng lỗ khác

Kết hợp với dừng cố định, dừng biến động, dừng thích nghi có thể được thử nghiệm.

Kết luận

Chiến lược này tích hợp phân tích xu hướng Moving Averages và quản lý dừng SuperTrends vào một chiến lược theo xu hướng hoàn chỉnh với việc dừng lỗ.


/*backtest
start: 2023-10-01 00:00:00
end: 2023-10-13 00:00:00
period: 30m
basePeriod: 15m
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/
// © 03.freeman

//@version=4
// strategy("FRAMA strategy", overlay=true,precision=6, initial_capital=1000,calc_on_every_tick=true, pyramiding=0, default_qty_type=strategy.fixed, default_qty_value=10000, currency=currency.EUR)
ma_src = input(title="MA FRAMA Source", type=input.source, defval=close)
ma_frama_len = input(title="MA FRAMA Length", type=input.integer, defval=12)
res = input(title="Resolution", type=input.resolution, defval="1W")
frama_FC = input(defval=1,minval=1, title="* Fractal Adjusted (FRAMA) Only - FC")
frama_SC = input(defval=200,minval=1, title="* Fractal Adjusted (FRAMA) Only - SC")
High = security(syminfo.tickerid, res, high)
Low = security(syminfo.tickerid, res, low)
source = security(syminfo.tickerid, res, ma_src)
enterRule = input(false,title = "Use supertrend for enter")
exitRule = input(false,title = "Use supertrend for exit")

ma(src, len) =>
    float result = 0
    int len1 = len/2
    e = 2.7182818284590452353602874713527
    w = log(2/(frama_SC+1)) / log(e) // Natural logarithm (ln(2/(SC+1))) workaround
    H1 = highest(High,len1)
    L1 = lowest(Low,len1)
    N1 = (H1-L1)/len1
    H2_ = highest(High,len1)
    H2 = H2_[len1]
    L2_ = lowest(Low,len1)
    L2 = L2_[len1]
    N2 = (H2-L2)/len1
    H3 = highest(High,len)
    L3 = lowest(Low,len)
    N3 = (H3-L3)/len
    dimen1 = (log(N1+N2)-log(N3))/log(2)
    dimen = iff(N1>0 and N2>0 and N3>0,dimen1,nz(dimen1[1]))
    alpha1 = exp(w*(dimen-1))
    oldalpha = alpha1>1?1:(alpha1<0.01?0.01:alpha1)
    oldN = (2-oldalpha)/oldalpha
    N = (((frama_SC-frama_FC)*(oldN-1))/(frama_SC-1))+frama_FC
    alpha_ = 2/(N+1)
    alpha = alpha_<2/(frama_SC+1)?2/(frama_SC+1):(alpha_>1?1:alpha_)
    frama = 0.0
    frama :=(1-alpha)*nz(frama[1]) + alpha*src
    result := frama
    result

frama = ma(sma(source,1),ma_frama_len)
signal = ma(frama,ma_frama_len)
plot(frama, color=color.red)
plot(signal, color=color.green)


longCondition = crossover(frama,signal)
shortCondition = crossunder(frama,signal)

Factor=input(3, minval=1,maxval = 100)
Pd=input(7, minval=1,maxval = 100)


Up=hl2-(Factor*atr(Pd))
Dn=hl2+(Factor*atr(Pd))

TrendUp = 0.0
TrendDown = 0.0
Trend = 0.0
Tsl = 0.0
TrendUp :=close[1]>TrendUp[1]? max(Up,TrendUp[1]) : Up
TrendDown :=close[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn

Trend := close > TrendDown[1] ? 1: close< TrendUp[1]? -1: nz(Trend[1],1)
Tsl := Trend==1? TrendUp: TrendDown

linecolor = Trend == 1 ? color.green : color.red

//plot(Tsl, color = linecolor , style =  plot.style_line , linewidth = 2,title = "SuperTrend")

plotshape(cross(close,Tsl) and close>Tsl , "Up Arrow", shape.triangleup,location.belowbar,color.green,0,0)
plotshape(cross(Tsl,close) and close<Tsl , "Down Arrow", shape.triangledown , location.abovebar, color.red,0,0)

plotarrow(Trend == 1 and Trend[1] == -1 ? Trend : na, title="Up Entry Arrow", colorup=color.lime, maxheight=60, minheight=50, transp=0)
plotarrow(Trend == -1 and Trend[1] == 1 ? Trend : na, title="Down Entry Arrow", colordown=color.red, maxheight=60, minheight=50, transp=0)


//  Strategy: (Thanks to JayRogers)
// === STRATEGY RELATED INPUTS ===
//tradeInvert     = input(defval = false, title = "Invert Trade Direction?")
// the risk management inputs
inpTakeProfit   = input(defval = 0, title = "Take Profit Points", minval = 0)
inpStopLoss     = input(defval = 0, title = "Stop Loss Points", minval = 0)
inpTrailStop    = input(defval = 0, title = "Trailing Stop Loss Points", minval = 0)
inpTrailOffset  = input(defval = 0, title = "Trailing Stop Loss Offset Points", minval = 0)

// === RISK MANAGEMENT VALUE PREP ===
// if an input is less than 1, assuming not wanted so we assign 'na' value to disable it.
useTakeProfit   = inpTakeProfit  >= 1 ? inpTakeProfit  : na
useStopLoss     = inpStopLoss    >= 1 ? inpStopLoss    : na
useTrailStop    = inpTrailStop   >= 1 ? inpTrailStop   : na
useTrailOffset  = inpTrailOffset >= 1 ? inpTrailOffset : na

// === STRATEGY - LONG POSITION EXECUTION ===
enterLong() => enterRule? (longCondition and Trend ==1):longCondition                                             // functions can be used to wrap up and work out complex conditions
exitLong() => exitRule and Trend == -1

strategy.entry(id = "Buy", long = true, when = enterLong() )             // use function or simple condition to decide when to get in
strategy.close(id = "Buy", when = exitLong() )                         // ...and when to get out

// === STRATEGY - SHORT POSITION EXECUTION ===
enterShort() => enterRule? (shortCondition and Trend ==-1):shortCondition
exitShort() => exitRule and Trend == 1

strategy.entry(id = "Sell", long = false, when = enterShort())
strategy.close(id = "Sell", when = exitShort() )

// === STRATEGY RISK MANAGEMENT EXECUTION ===
// finally, make use of all the earlier values we got prepped
strategy.exit("Exit Buy", from_entry = "Buy", profit = useTakeProfit, loss = useStopLoss, trail_points = useTrailStop, trail_offset = useTrailOffset)
strategy.exit("Exit Sell", from_entry = "Sell", profit = useTakeProfit, loss = useStopLoss, trail_points = useTrailStop, trail_offset = useTrailOffset)

// === Backtesting Dates === thanks to Trost

testPeriodSwitch = input(false, "Custom Backtesting Dates")
testStartYear = input(2020, "Backtest Start Year")
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testStartHour = input(0, "Backtest Start Hour")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,testStartHour,0)
testStopYear = input(2020, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testStopHour = input(23, "Backtest Stop Hour")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay,testStopHour,0)
testPeriod() =>
    time >= testPeriodStart and time <= testPeriodStop ? true : false
isPeriod = true
// === /END

if not isPeriod
    strategy.cancel_all()
    strategy.close_all()

Thêm nữa