Chiến lược dải băng trung bình di chuyển trơn tru

Tác giả:ChaoZhang, Ngày: 2023-12-11 14:48:35
Tags:

img

Tổng quan

Chiến lược này xây dựng một dải giá mượt mà bằng cách sử dụng các đường trung bình di chuyển mượt mà và tích hợp các đường trung bình di chuyển mượt mà khác nhau để lọc xu hướng trong thời gian thực.

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

  1. Xây dựng một dải giá trơn tru để theo dõi sự thay đổi giá bằng cách sử dụng các đường trung bình di chuyển trơn tru.
  2. Chiến lược hỗ trợ các loại trung bình động khác nhau như phương pháp tính toán cho các đường trung bình động trơn tru, chẳng hạn như EMA, SMMA, KAMA, v.v.
  3. Nó hỗ trợ 1-5 lớp gọn gàng trên các đường trung bình động này để có được một dải giá thậm chí còn mượt mà hơn.
  4. Nó cũng hỗ trợ thêm Bollinger Bands giữa giá và đường trung bình động để nắm bắt tốt hơn sự thay đổi giá.
  5. Bằng cách kích hoạt bộ lọc trung bình động bổ sung, nó có thể lọc ra biến động tốt hơn và xác định hướng xu hướng.
  6. Kết hợp với các chỉ số nhận dạng mẫu, nó có thể tự động xác định tín hiệu mua và bán.

Bằng cách xây dựng một dải giá mượt mà để nắm bắt xu hướng giá, và tích hợp bộ lọc trung bình động để xác nhận hướng xu hướng, chiến lược này thuộc về một chiến lược theo xu hướng điển hình. Bằng cách điều chỉnh các tham số, nó có thể được điều chỉnh linh hoạt cho các sản phẩm và khung thời gian khác nhau.

Ưu điểm

  1. Xây dựng dải giá có thể theo dõi các thay đổi xu hướng giá một cách mượt mà hơn, giảm khả năng bỏ lỡ cơ hội.
  2. Hỗ trợ nhiều loại trung bình động cho phép lựa chọn các trung bình động phù hợp dựa trên các khung thời gian và sản phẩm khác nhau, cải thiện khả năng thích nghi của chiến lược.
  3. 1-5 lớp của sự trơn tru xếp chồng lên nhau có thể cải thiện đáng kể khả năng theo dõi các thay đổi giá và nắm bắt các điểm đảo ngược xu hướng chính xác hơn.
  4. Bộ lọc trung bình động có thể giảm hiệu quả các tín hiệu không hợp lệ và cải thiện tỷ lệ thắng.
  5. Bằng cách điều chỉnh độ dài trung bình động, nó có thể được điều chỉnh theo các khung thời gian khác nhau.
  6. Hỗ trợ màn hình kính đen cho phép quan sát rõ ràng và trực quan xu hướng dải giá.

Rủi ro

  1. Sức mạnh trong việc theo dõi xu hướng dài hạn, nhưng kém trong việc theo dõi và phản ứng với biến động ngắn hạn, có xu hướng tạo ra nhiều tín hiệu không hợp lệ hơn trong các thị trường giới hạn phạm vi.
  2. Trong các đợt tăng giá và giảm giá mạnh mẽ, sự tụt hậu của các đường trung bình di chuyển mượt mà có thể bỏ lỡ thời điểm vào tốt nhất.
  3. Việc xếp chồng chéo các đường trung bình động quá nhiều có thể làm trơn tru quá nhiều các thay đổi giá và gây ra sự xác định không chính xác các điểm mua và bán.
  4. Nếu các thông số chiều dài trung bình động được bật được đặt không đúng cách, nó có thể tạo ra một số lượng lớn tín hiệu sai.

Giải pháp:

  1. Giảm ngắn các chiều dài trung bình động để tăng tốc phản ứng với sự thay đổi giá.
  2. Điều chỉnh thời gian xếp chồng để giảm quá mịn.
  3. Tối ưu hóa và thử nghiệm các kết hợp trung bình động để chọn các thông số tối ưu.
  4. Sử dụng xác minh nhiều khung thời gian với các chỉ số khác để giảm tín hiệu sai.

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

  1. Kiểm tra và tối ưu hóa sự kết hợp của các loại trung bình động để chọn các thông số tối ưu.
  2. Kiểm tra và tối ưu hóa các thông số chiều dài trung bình động để thích nghi với nhiều sản phẩm và khung thời gian hơn.
  3. Hãy thử các thời gian xếp chồng lỏng khác nhau để tìm điểm cân bằng tối ưu.
  4. Hãy thử thêm Bollinger Bands như một chỉ số phụ trợ.
  5. Kiểm tra các trung bình động bổ sung khác nhau như bộ lọc.
  6. Sử dụng xác minh nhiều khung thời gian với các chỉ số khác.

Kết luận

Chiến lược này thuộc về một chiến lược theo xu hướng điển hình liên tục theo dõi xu hướng giá bằng cách xây dựng các dải trung bình di chuyển mượt mà và tránh các tín hiệu không hợp lệ với các bộ lọc hỗ trợ. Ưu điểm của nó nằm trong việc xây dựng các dải giá mượt mà để nắm bắt tốt hơn các biến trong xu hướng giá. Nó cũng có một số rủi ro chậm trễ. Bằng cách tối ưu hóa tham số và tối ưu hóa chỉ số, hiệu suất chiến lược có thể được cải thiện liên tục và đáng nghiên cứu thêm.


/*backtest
start: 2023-12-03 00:00:00
end: 2023-12-10 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// Copyright (c) 2007-present Jurik Research and Consulting. All rights reserved.
// Copyright (c) 2018-present, Alex Orekhov (everget)
// Thanks to everget for code for more advanced moving averages
// Smooth Moving Average Ribbon [STRATEGY] @PuppyTherapy script may be freely distributed under the MIT license.
strategy( title="Smooth Moving Average Ribbon [STRATEGY] @PuppyTherapy", overlay=true )

// ---- CONSTANTS ----
lsmaOffset = 1
almaOffset = 0.85
almaSigma  = 6
phase = 2
power = 2

// ---- GLOBAL FUNCTIONS ----
kama(src, len)=>
    xvnoise = abs(src - src[1])
    nfastend = 0.666
    nslowend = 0.0645
    nsignal = abs(src - src[len])
    nnoise = sum(xvnoise, len)
    nefratio = iff(nnoise != 0, nsignal / nnoise, 0)
    nsmooth = pow(nefratio * (nfastend - nslowend) + nslowend, 2)
    nAMA = 0.0
    nAMA := nz(nAMA[1]) + nsmooth * (src - nz(nAMA[1]))

t3(src, len)=>
    xe1_1 = ema(src,    len)
    xe2_1 = ema(xe1_1,  len)
    xe3_1 = ema(xe2_1,  len)
    xe4_1 = ema(xe3_1,  len)
    xe5_1 = ema(xe4_1,  len)
    xe6_1 = ema(xe5_1,  len)
    b_1 = 0.7
    c1_1 = -b_1*b_1*b_1
    c2_1 = 3*b_1*b_1+3*b_1*b_1*b_1
    c3_1 = -6*b_1*b_1-3*b_1-3*b_1*b_1*b_1
    c4_1 = 1+3*b_1+b_1*b_1*b_1+3*b_1*b_1
    nT3Average_1 = c1_1 * xe6_1 + c2_1 * xe5_1 + c3_1 * xe4_1 + c4_1 * xe3_1
    
// The general form of the weights of the (2m + 1)-term Henderson Weighted Moving Average
getWeight(m, j) =>
    numerator = 315 * (pow(m + 1, 2) - pow(j, 2)) * (pow(m + 2, 2) - pow(j, 2)) * (pow(m + 3, 2) - pow(j, 2)) * (3 * pow(m + 2, 2) - 11 * pow(j, 2) - 16)
    denominator = 8 * (m + 2) * (pow(m + 2, 2) - 1) * (4 * pow(m + 2, 2) - 1) * (4 * pow(m + 2, 2) - 9) * (4 * pow(m + 2, 2) - 25)

    denominator != 0
         ? numerator / denominator
         : 0

hwma(src, termsNumber) =>
    sum = 0.0
    weightSum = 0.0
    
    termMult = (termsNumber - 1) / 2

    for i = 0 to termsNumber - 1
        weight = getWeight(termMult, i - termMult)
        sum := sum + nz(src[i]) * weight
        weightSum := weightSum + weight

    sum / weightSum

get_jurik(length, phase, power, src)=>
    phaseRatio = phase < -100 ? 0.5 : phase > 100 ? 2.5 : phase / 100 + 1.5
    beta = 0.45 * (length - 1) / (0.45 * (length - 1) + 2)
    alpha = pow(beta, power)
    jma = 0.0
    e0 = 0.0
    e0 := (1 - alpha) * src + alpha * nz(e0[1])
    e1 = 0.0
    e1 := (src - e0) * (1 - beta) + beta * nz(e1[1])
    e2 = 0.0
    e2 := (e0 + phaseRatio * e1 - nz(jma[1])) * pow(1 - alpha, 2) + pow(alpha, 2) * nz(e2[1])
    jma := e2 + nz(jma[1])

variant(src, type, len ) =>
    v1 = sma(src, len)                                                  // Simple
    v2 = ema(src, len)                                                  // Exponential
    v3 = 2 * v2 - ema(v2, len)                                          // Double Exponential
    v4 = 3 * (v2 - ema(v2, len)) + ema(ema(v2, len), len)               // Triple Exponential
    v5 = wma(src, len)                                                  // Weighted
    v6 = vwma(src, len)                                                 // Volume Weighted
    v7 = na(v5[1]) ? sma(src, len) : (v5[1] * (len - 1) + src) / len    // Smoothed
    v8 = wma(2 * wma(src, len / 2) - wma(src, len), round(sqrt(len)))   // Hull
    v9 = linreg(src, len, lsmaOffset)                                   // Least Squares
    v10 = alma(src, len, almaOffset, almaSigma)                         // Arnaud Legoux
    v11 = kama(src, len)                                                // KAMA
    ema1 = ema(src, len)
    ema2 = ema(ema1, len)
    v13 = t3(src, len)                                                  // T3
    v14 = ema1+(ema1-ema2)                                              // Zero Lag Exponential
    v15 = hwma(src, len)                                                // Henderson Moving average thanks to  @everget
    ahma = 0.0
    ahma := nz(ahma[1]) + (src - (nz(ahma[1]) + nz(ahma[len])) / 2) / len //Ahrens Moving Average 
    v16 = ahma
    v17 = get_jurik( len, phase, power, src) 
    type=="EMA"?v2 : type=="DEMA"?v3 : type=="TEMA"?v4 : type=="WMA"?v5 : type=="VWMA"?v6 :
     type=="SMMA"?v7 : type=="Hull"?v8 : type=="LSMA"?v9 : type=="ALMA"?v10 : type=="KAMA"?v11 :
     type=="T3"?v13 : type=="ZEMA"?v14 : type=="HWMA"?v15 : type=="AHMA"?v16 : type=="JURIK"?v17 : v1

smoothMA(o, h, l, c, maLoop, type, len) =>
	ma_o = 0.0
	ma_h = 0.0
	ma_l = 0.0
	ma_c = 0.0
	if maLoop == 1
		ma_o := variant(o, type, len)
		ma_h := variant(h, type, len)
		ma_l := variant(l, type, len)
		ma_c := variant(c, type, len)
	if maLoop == 2
		ma_o := variant(variant(o ,type, len),type, len)
		ma_h := variant(variant(h ,type, len),type, len)
		ma_l := variant(variant(l ,type, len),type, len)
		ma_c := variant(variant(c ,type, len),type, len)
	if maLoop == 3
		ma_o := variant(variant(variant(o ,type, len),type, len),type, len)
		ma_h := variant(variant(variant(h ,type, len),type, len),type, len)
		ma_l := variant(variant(variant(l ,type, len),type, len),type, len)
		ma_c := variant(variant(variant(c ,type, len),type, len),type, len)
	if maLoop == 4
		ma_o := variant(variant(variant(variant(o ,type, len),type, len),type, len),type, len)
		ma_h := variant(variant(variant(variant(h ,type, len),type, len),type, len),type, len)
		ma_l := variant(variant(variant(variant(l ,type, len),type, len),type, len),type, len)
		ma_c := variant(variant(variant(variant(c ,type, len),type, len),type, len),type, len)
	if maLoop == 5
		ma_o := variant(variant(variant(variant(variant(o ,type, len),type, len),type, len),type, len),type, len)
		ma_h := variant(variant(variant(variant(variant(h ,type, len),type, len),type, len),type, len),type, len)
		ma_l := variant(variant(variant(variant(variant(l ,type, len),type, len),type, len),type, len),type, len)
		ma_c := variant(variant(variant(variant(variant(c ,type, len),type, len),type, len),type, len),type, len)
    [ma_o, ma_h, ma_l, ma_c]

smoothHA( o, h, l, c ) =>
    hao = 0.0
    hac = ( o + h + l + c ) / 4
    hao := na(hao[1])?(o + c / 2 ):(hao[1] + hac[1])/2
    hah = max(h, max(hao, hac))
    hal = min(l, min(hao, hac))
	[hao, hah, hal, hac]

// ---- Main Ribbon ----
haSmooth   = input(true, title=" Use HA as source ? " )
length     = input(11, title=" MA1 Length", minval=1, maxval=1000)
maLoop     = input(3, title=" Nr. of MA1 Smoothings ", minval=1, maxval=5)
type       = input("EMA", title="MA Type", options=["SMA", "EMA", "DEMA", "TEMA", "WMA", "VWMA", "SMMA", "Hull", "LSMA", "ALMA", "KAMA", "ZEMA", "HWMA", "AHMA", "JURIK", "T3"])
haSmooth2  = input(true, title=" Use HA as source ? " )

// ---- Trend ----
ma_use    = input(true, title=" ----- Use MA Filter ( For Lower Timeframe Swings / Scalps ) ? ----- " )
ma_source = input(defval = close, title = "MA - Source", type = input.source)
ma_length = input(100,title="MA - Length", minval=1 )
ma_type   = input("SMA", title="MA - Type", options=["SMA", "EMA", "DEMA", "TEMA", "WMA", "VWMA", "SMMA", "Hull", "LSMA", "ALMA", "KAMA", "ZEMA", "HWMA", "AHMA", "JURIK", "T3"])
ma_useHA  = input(defval = false, title = "Use HA Candles as Source ?")
ma_rsl    = input(true, title = "Use Rising / Falling Logic ?" )

// ---- BODY SCRIPT ----
[ ha_open, ha_high, ha_low, ha_close ] = smoothHA(open, high, low, close)

_open_ma  = haSmooth ? ha_open : open
_high_ma  = haSmooth ? ha_high : high
_low_ma   = haSmooth ? ha_low : low
_close_ma = haSmooth ? ha_close : close

[ _open, _high, _low, _close ] = smoothMA( _open_ma, _high_ma, _low_ma, _close_ma, maLoop, type, length)
[ ha_open2, ha_high2, ha_low2, ha_close2 ] = smoothHA(_open, _high, _low, _close)

_open_ma2  = haSmooth2 ? ha_open2 : _open
_high_ma2  = haSmooth2 ? ha_high2 : _high
_low_ma2   = haSmooth2 ? ha_low2 : _low
_close_ma2 = haSmooth2 ? ha_close2 : _close

ribbonColor = _close_ma2 > _open_ma2 ? color.lime : color.red
p_open  = plot(_open_ma2,  title="Ribbon - Open",   color=ribbonColor, transp=70)
p_close = plot(_close_ma2, title="Ribbon - Close",  color=ribbonColor, transp=70)
fill(p_open, p_close, color = ribbonColor, transp = 40 )

// ----- FILTER

ma = 0.0
if ma_use == true
    ma := variant( ma_useHA ? ha_close : ma_source, ma_type,  ma_length )

maFilterShort = ma_use ? ma_rsl ? falling(ma,1) : ma_useHA ? ha_close : close < ma : true 
maFilterLong  = ma_use ? ma_rsl ? rising(ma,1) : ma_useHA ? ha_close : close > ma : true 


colorTrend = rising(ma,1) ? color.green : color.red
plot( ma_use ? ma : na, title="MA Trend",  color=colorTrend, transp=80, transp=70, linewidth = 5)

long     = crossover(_close_ma2, _open_ma2 ) and maFilterLong
short    = crossunder(_close_ma2, _open_ma2 ) and maFilterShort
closeAll = cross(_close_ma2, _open_ma2 )

plotshape( short , title="Short", color=color.red,  transp=80, style=shape.triangledown, location=location.abovebar, size=size.small)
plotshape( long ,  title="Long",  color=color.lime, transp=80, style=shape.triangleup,   location=location.belowbar, size=size.small)

//* Backtesting Period Selector | Component *//
//* Source: https://www.tradingview.com/script/eCC1cvxQ-Backtesting-Period-Selector-Component *//
testStartYear   = input(2018, "Backtest Start Year",minval=1980)
testStartMonth  = input(1, "Backtest Start Month",minval=1,maxval=12)
testStartDay    = input(1, "Backtest Start Day",minval=1,maxval=31)
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,0,0)
testStopYear    = 9999 //input(9999, "Backtest Stop Year",minval=1980)
testStopMonth   = 12 // input(12, "Backtest Stop Month",minval=1,maxval=12)
testStopDay     = 31 //input(31, "Backtest Stop Day",minval=1,maxval=31)
testPeriodStop  = timestamp(testStopYear,testStopMonth,testStopDay,0,0)
testPeriod() => time >= testPeriodStart and time <= testPeriodStop ? true : false

if testPeriod() and long
    strategy.entry( "long", strategy.long )

if testPeriod() and short
    strategy.entry( "short", strategy.short )
    
if closeAll
    strategy.close_all( when = closeAll )


Thêm nữa