Chiến lược dải trung bình động được làm mịn


Ngày tạo: 2023-12-11 14:48:35 sửa đổi lần cuối: 2023-12-11 14:48:35
sao chép: 2 Số nhấp chuột: 656
1
tập trung vào
1621
Người theo dõi

Chiến lược dải trung bình động được làm mịn

Tổng quan

Chiến lược này là một trong những chiến lược theo xu hướng điển hình bằng cách sử dụng đường trung bình di chuyển mịn để xây dựng các dải giá mịn và tích hợp nhiều đường trung bình di chuyển mịn để thực hiện chức năng lọc xu hướng trong thời gian thực.

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

  1. Bằng cách xây dựng các dải giá mịn, sử dụng các đường trung bình di chuyển mịn để theo dõi sự thay đổi giá.
  2. Các chính sách hỗ trợ nhập nhiều loại moving average khác nhau như EMA, SMMA, KAMA.
  3. Hỗ trợ cho các đường trung bình di chuyển này được làm mịn từ 1-5 lần để có được một dải giá mịn hơn.
  4. Ngoài ra, nó cũng hỗ trợ việc sử dụng các dải Brinks giữa giá và đường trung bình di chuyển để nắm bắt tốt hơn sự thay đổi của giá cả.
  5. Bằng cách bật bộ lọc trung bình di chuyển bổ sung, bạn có thể lọc tốt hơn các biến động và nhận biết hướng xu hướng. Bộ lọc cũng hỗ trợ nhiều loại trung bình di chuyển.
  6. Kết hợp với các chỉ số nhận dạng hình dạng, nhận dạng tự động của tín hiệu mua và bán.

Chiến lược này là một chiến lược theo dõi xu hướng điển hình bằng cách tạo ra các dải giá mịn để nắm bắt xu hướng giá và tích hợp các bộ lọc trung bình di chuyển để xác nhận xu hướng. Bằng cách điều chỉnh các tham số, nó có thể linh hoạt thích ứng với môi trường thị trường khác nhau trong các chu kỳ khác nhau.

Lợi thế chiến lược

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

Rủi ro chiến lược

  1. Theo dõi xu hướng dài hạn mạnh mẽ, nhưng theo dõi và phản ứng với biến động ngắn hạn kém hơn, dễ tạo ra nhiều tín hiệu vô hiệu trong tình huống chấn động.
  2. Trong một thời gian giá cả thay đổi nhanh chóng, các đường trung bình di chuyển trơn có thể bị tụt hậu và có thể bỏ lỡ thời gian đầu vào tốt nhất.
  3. Một số trung bình di chuyển chồng lên nhau có thể làm thay đổi giá thành quá trơn, dẫn đến việc không thể nhận ra điểm mua và bán.
  4. Nếu các tham số chiều dài của đường trung bình di chuyển được bật không được thiết lập đúng, nó có thể dẫn đến việc tạo ra một số lượng lớn các tín hiệu giả.

Giải pháp:

  1. Giảm độ dài của đường trung bình di chuyển một cách thích hợp để phản ứng nhanh hơn với sự thay đổi giá.
  2. Điều chỉnh số lần xếp chồng lên nhau để giảm khả năng bị mịn quá mức.
  3. Tối ưu hóa và thử nghiệm các kết hợp trung bình di chuyển, chọn tham số tốt nhất.
  4. Kết hợp với các chỉ số khác để xác minh nhiều khung thời gian, giảm tỷ lệ tín hiệu giả.

Hướng tối ưu hóa chiến lược

  1. Kiểm tra tối ưu hóa các loại moving average, chọn tham số tốt nhất.
  2. Kiểm tra tối ưu hóa các tham số chiều dài của đường trung bình di chuyển để phù hợp với các giống và chu kỳ thời gian rộng hơn.
  3. Cố gắng tạo ra các kết nối khác nhau để tìm ra điểm cân bằng tốt nhất.
  4. Hãy thử thêm một đoạn Brin để hỗ trợ.
  5. Kiểm tra các trung bình di chuyển bổ sung khác nhau như là bộ lọc.
  6. Xác thực nhiều khung thời gian kết hợp với các chỉ số khác.

Tóm tắt

Chiến lược này là một trong những chiến lược theo dõi xu hướng điển hình, theo dõi liên tục xu hướng giá bằng cách xây dựng dải trung bình di chuyển mịn, kết hợp với bộ lọc hỗ trợ để tránh tín hiệu không hiệu quả. Ưu điểm của chiến lược nằm ở việc xây dựng dải giá mịn, có thể nắm bắt tốt hơn sự biến đổi của xu hướng giá.

Mã nguồn chiến lược
/*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 )