Chiến lược tìm kiếm xu hướng bằng laser kép

Tác giả:ChaoZhang, Ngày: 2023-11-06 10:01:42
Tags:

img

Tổng quan

Chiến lược này sử dụng Bollinger Bands, Keltner Channels và Adaptive Relative Strength Index để xác định hướng xu hướng hiện tại, kết hợp với Parabolic SAR để thời gian nhập.

Nguyên tắc

Chiến lược này kết hợp ba chỉ số kỹ thuật sau đây để xác định xu hướng hiện tại:

  1. SQUEEZE Momentum Indicator: Tính toán Bollinger Bands và Keltner Channels. Khi hai dải chồng chéo, nó tạo ra một sự ép và báo hiệu một sự thay đổi xu hướng sắp xảy ra. Nó trả về trạng thái ép và độ nghiêng hồi quy tuyến tính.

  2. RSI khối lượng cân nhắc: Tính toán RSI cân nhắc theo khối lượng. Sử dụng điểm giữa để xác định mức mua quá mức / bán quá mức. Nó nhấn mạnh sự thay đổi khối lượng.

  3. SAR Parabolic: Đánh giá vị trí của giá hiện tại so với đường SAR. SAR trên giá chỉ ra xu hướng giảm trong khi SAR dưới giá chỉ ra xu hướng tăng.

Chiến lược sử dụng Bollinger Bands để xác định hướng xu hướng, Keltner Channels để tinh chỉnh nó, RSI để tìm cơ hội đảo ngược khi mua quá mức / bán quá mức và SAR để thời gian nhập.

  1. Tính toán Bollinger Bands, kênh Keltner, chỉ số squeeze.

  2. Tính toán chỉ số RSI theo trọng lượng khối lượng. chỉ số RSI trên điểm giữa cho thấy xu hướng tăng, dưới điểm trung xu hướng giảm.

  3. Tính toán SAR Parabolic. SAR dưới giá cho thấy xu hướng tăng, trên giá cho thấy xu hướng giảm.

  4. Kết hợp ba chỉ số: khi squeeze xảy ra, RSI đi trên điểm trung bình, SAR dưới giá, một tín hiệu dài được tạo ra. Khi squeeze xảy ra, RSI đi dưới điểm trung bình, SAR trên giá, một tín hiệu ngắn được tạo ra.

  5. Khi một tín hiệu được kích hoạt, kiểm tra xem các phán đoán của ba chỉ số trên thanh trước có trái ngược với tín hiệu hiện tại không.

  6. Thiết lập dừng lỗ và lấy lợi nhuận sau khi nhập, dừng lỗ sau.

Ưu điểm

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

  1. Sự kết hợp của nhiều chỉ số cải thiện độ chính xác của phán đoán xu hướng. Squeeze phát hiện chính xác những thay đổi xu hướng, RSI xác định rõ mức mua quá mức / bán quá mức, SAR chính xác lần nhập.

  2. Lý thuyết chỉ số là đơn giản và dễ hiểu.

  3. Việc xác nhận nhiều chỉ số giúp lọc các sự đột phá sai.

  4. Các cơ chế dừng lỗ và lấy lợi nhuận khóa lợi nhuận và hạn chế rủi ro.

  5. Dữ liệu backtest rộng rãi đảm bảo độ tin cậy.

Rủi ro

Ngoài ra còn có một số rủi ro:

  1. Logic đầu vào dài và ngắn tương tự nhau và có thể tạo ra các tín hiệu mâu thuẫn.

  2. Tất cả các chỉ số sử dụng tối ưu hóa tham số, rủi ro quá phù hợp.

  3. Tần suất giao dịch cao, cần kiểm soát kích thước vị trí.

  4. Stop loss có thể quá gần và dễ bị dừng lại.

Giải pháp:

  1. Thêm kiểm tra độ bền trên các phán đoán chỉ số để tránh dao động tín hiệu.

  2. Sử dụng phân tích đi trước để điều chỉnh các thông số và ngăn ngừa quá tải.

  3. Đặt kích thước kim tự tháp để kiểm soát vị trí theo hướng.

  4. Kiểm tra phạm vi dừng lỗ khác nhau để tối ưu hóa giá dừng lỗ.

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

Một số hướng để tối ưu hóa chiến lược:

  1. Tối ưu hóa các thông số chỉ số cho sự ổn định.

  2. Thêm vị trí kích thước logic như cố định / tỷ lệ phần trăm bằng nhau.

  3. Kiểm tra các phương pháp dừng lỗ khác nhau như biến động hoặc dừng tuyến tính, đặt vị trí bằng không vv

  4. Thêm quản lý tiền bạc như định dạng vị trí phân số cố định.

  5. Sử dụng các mô hình máy học để nhập và thoát động.

  6. Thêm các cơ chế phòng ngừa bằng cách đi cả dài và ngắn để giảm rủi ro hệ thống liên quan.

  7. Xem xét nhiều chỉ số hơn và xây dựng các cơ chế bỏ phiếu để cải thiện độ chính xác.

Kết luận

Chiến lược này có logic rõ ràng sử dụng nhiều chỉ số để xác định hướng xu hướng và thông minh bước vào squeeze. Cơ chế dừng lỗ và lấy lợi nhuận hạn chế rủi ro. Tối ưu hóa tham số và kiểm soát rủi ro có thể cải thiện thêm kết quả backtest và trực tiếp.


/*backtest
start: 2023-10-06 00:00:00
end: 2023-11-05 00:00:00
period: 1h
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/
// © XaviZ

//#####©ÉÉÉɶN###############################################
//####*..´´´´´´,,,»ëN########################################
//###ë..´´´´´´,,,,,,''%©#####################################
//###'´´´´´´,,,,,,,'''''?¶###################################
//##o´´´´´´,,,,,,,''''''''*©#################################
//##'´´´´´,,,,,,,'''''''^^^~±################################
//#±´´´´´,,,,,,,''''''''^í/;~*©####æ%;í»~~~~;==I±N###########
//#»´´´´,,,,,,'''''''''^;////;»¶X/í~~/~~~;=~~~~~~~~*¶########
//#'´´´,,,,,,''''''''^^;////;%I^~/~~/~~~=~~~;=?;~~~~;?ë######
//©´´,,,,,,,''''''''^^~/////X~/~~/~~/~~»í~~=~~~~~~~~~~^;É####
//¶´,,,,,,,''''''''^^^;///;%;~/~~;í~~»~í?~?~~~?I/~~~~?*=íÑ###
//N,,,,,,,'''''''^^^^^///;;o/~~;;~~;£=»í»;IX/=~~~~~~^^^^'*æ##
//#í,,,,,''''''''^^^^^;;;;;o~»~~~~íX//~/»~;í?IíI»~~^/*?'''=N#
//#%,,,'''''''''^^^^^^í;;;;£;~~~//»I»/£X/X/»í*&~~~^^^^'^*~'É#
//#©,,''''''''^^^^^^^^~;;;;&/~/////*X;í;o*í»~=*?*===^'''''*£#
//##&''''''''^^^^^^^^^^~;;;;X=í~~~»;;;/~;í»~»±;^^^^^';=''''É#
//##N^''''''^^^^^^^^^^~~~;;;;/£;~~/»~~»~~///o~~^^^^''''?^',æ#
//###Ñ''''^^^^^^^^^^^~~~~~;;;;;í*X*í»;~~IX?~~^^^^/?'''''=,=##
//####X'''^^^^^^^^^^~~~~~~~~;;íííííí~~í*=~~~~Ií^'''=''''^»©##
//#####£^^^^^^^^^^^~~~~~~~~~~~íííííí~~~~~*~^^^;/''''='',,N###
//######æ~^^^^^^^^~~~~~~~~~~~~~~íííí~~~~~^*^^^'=''''?',,§####
//########&^^^^^^~~~~~~~~~~~~~~~~~~~~~~~^^=^^''=''''?,íN#####
//#########N?^^~~~~~~~~~~~~~~~~~~~~~~~~^^^=^''^?''';í@#######
//###########N*~~~~~~~~~~~~~~~~~~~~~~~^^^*'''^='''/É#########
//##############@;~~~~~~~~~~~~~~~~~~~^^~='''~?'';É###########
//#################É=~~~~~~~~~~~~~~^^^*~'''*~?§##############
//#####################N§£I/~~~~~~»*?~»o§æN##################

//@version=4
strategy(title="M-SQUEEZE", overlay = true)

//study(title="M-SQUEEZE", overlay = true)

src = input(close, "SOURCE", type = input.source)

// ███▓▒░░ VARIABLES ░░▒▓███

var bool longCond = na, var bool shortCond = na
var int CondIni_long0 = 0, var int CondIni_short0 = 0
var int CondIni_long = 0, var int CondIni_short = 0
var float last_open_longCondition = na, var float last_open_shortCondition = na
var int last_longCondition0 = na, var int last_shortCondition0 = na
var int last_longCondition = na, var int last_shortCondition = na
var bool long_tp = na, var bool short_tp = na
var int last_long_tp = na, var int last_short_tp = na
var bool Final_Long_tp = na, var bool Final_Short_tp = na
var bool SMI_longCond = na, var bool SMI_shortCond = na
var bool RSI_longCond = na, var bool RSI_shortCond = na
var bool ADX_longCond = na, var bool ADX_shortCond = na
var bool SAR_longCond = na, var bool SAR_shortCond = na
var bool Final_longCondition0 = na, var bool Final_shortCondition0 = na
var bool Final_longCondition = na, var bool Final_shortCondition = na

// ███▓▒░░ SQUEEZE MOMENTUM INDICATOR ░░▒▓███

Act_SMI = input(true, "SQUEEZE MOMENTUM INDICATOR")
BB_length = input(85, title="BOLLINGER BANDS LENGTH", minval = 1)
BB_mult = input(2.1, title="BOLLINGER BANDS MULTI-FACTOR", minval = 0.1, step = 0.1)
KC_length = input(38, title="KELTNER CHANNEL LENGTH", minval = 1)
KC_mult = input(2.0, title="KELTNER CHANNEL MULTI-FACTOR", minval = 0.1, step = 0.1)

SQUEEZE_M(_src,_BB_length,_BB_mult,_KC_length,_KC_mult)=>

    // Calculate BB
    basis = sma(_src, _BB_length)
    dev = _BB_mult * stdev(_src, _BB_length)
    upperBB = basis + dev
    lowerBB = basis - dev
    // Calculate KC
    ma = sma(src, _KC_length)
    rangema = sma(tr, _KC_length)
    upperKC = ma + rangema * _KC_mult
    lowerKC = ma - rangema * _KC_mult
    // Squeeze
    sqzOn = lowerBB > lowerKC and upperBB < upperKC
    sqzOff = lowerBB < lowerKC and upperBB > upperKC
    nosqz = sqzOn == false and sqzOff == false
    // Linear Regression curve
    val = linreg(_src - avg(avg(highest(high, _KC_length), lowest(low, _KC_length)), sma(close, _KC_length)), _KC_length, 0)
    [nosqz,val]
    
[NOSQZ,VAL] = SQUEEZE_M(src,BB_length,BB_mult,KC_length,KC_mult)

barcolor(iff(VAL > 0, iff(VAL > nz(VAL[1]), color.lime, color.green), iff(VAL < nz(VAL[1]), color.red, color.maroon)))

// ███▓▒░░ SAR ░░▒▓███

Act_SAR = input(true, "PARABOLIC SAR")
Sst = input (0.73, "SAR STAR", step=0.01, minval = 0.01)
Sinc = input (0.5, "SAR INC", step=0.01, minval = 0.01)
Smax = input (0.06, "SAR MAX", step=0.01, minval = 0.01)

SAR = sar(Sst, Sinc, Smax)
plot(SAR, style = plot.style_cross, title = "SAR")

// ███▓▒░░ RSI VOLUME WEIGHTED ░░▒▓███

Act_RSI = input(true, "RSI VOLUME WEIGHTED")
RSI_len = input(22, "RSI LENGHT", minval = 1)
RSI_obos = input(45,title="RSI CENTER LINE", type=input.integer, minval = 1)

WiMA(_src, _length)=> 
    var float MA_s=0.0
    MA_s:=(_src + nz(MA_s[1] * (_length-1)))/_length
    MA_s

RSI_Volume(fv, length)=>	
	up=iff(fv>fv[1],abs(fv-fv[1])*volume,0)
	dn=iff(fv<fv[1],abs(fv-fv[1])*volume,0)
	upt=WiMA(up,length)
	dnt=WiMA(dn,length)
	100*(upt/(upt+dnt))

RSI_V = RSI_Volume(src, RSI_len)

// ███▓▒░░ STRATEGY ░░▒▓███

SMI_longCond := (Act_SMI ? (VAL > 0 and (VAL > nz(VAL[1])) and not NOSQZ) : RSI_longCond) 
RSI_longCond := (Act_RSI ? (RSI_V > RSI_obos) : SAR_longCond)
SAR_longCond := (Act_SAR ? (SAR < close) : SMI_longCond)

SMI_shortCond := (Act_SMI ? (VAL < 0 and (VAL < nz(VAL[1])) and not NOSQZ) : RSI_shortCond) 
RSI_shortCond := (Act_RSI ? (RSI_V < RSI_obos) : SAR_shortCond)
SAR_shortCond := (Act_SAR ? (SAR > close) : SMI_shortCond)

longCond := SMI_longCond and RSI_longCond and SAR_longCond
shortCond := SMI_shortCond and RSI_shortCond and SAR_shortCond

CondIni_long0 := longCond ? 1 : shortCond ? -1 : CondIni_long0[1]
CondIni_short0 := longCond ? 1 : shortCond ? -1 : CondIni_short0[1]

longCondition0 = (longCond and CondIni_long0[1] == -1)
shortCondition0 = (shortCond and CondIni_short0[1] == 1)

CondIni_long := longCond[1] ? 1 : shortCond[1] ? -1 : CondIni_long[1]
CondIni_short := longCond[1] ? 1 : shortCond[1] ? -1 : CondIni_short[1]

longCondition = (longCond[1] and CondIni_long[1] == -1)
shortCondition = (shortCond[1] and CondIni_short[1] == 1)

// ███▓▒░░ ALERTS & SIGNALS ░░▒▓███

plotshape(longCondition, title = "Long Signal", style = shape.triangleup, location = location.belowbar, color = color.blue, transp = 0, size = size.tiny)
plotshape(shortCondition, title = "Short Signal", style = shape.triangledown, location = location.abovebar, color = #FF0000, transp = 0, size = size.tiny)

//alertcondition(longCondition, title="Long Alert", message = "LONG") 
//alertcondition(shortCondition, title="Short Alert", message = "SHORT")

// ███▓▒░░ BACKTESTING ░░▒▓███

testStartYear = input(2018, "BACKTEST START YEAR", minval = 1980, maxval = 2222) 
testStartMonth = input(01, "BACKTEST START MONTH", minval = 1, maxval = 12)
testStartDay = input(01, "BACKTEST START DAY", minval = 1, maxval = 31)
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,0,0)
testStopYear = input(2222, "BACKTEST STOP YEAR", minval=1980, maxval = 2222)
testStopMonth = input(12, "BACKTEST STOP MONTH", minval=1, maxval=12)
testStopDay = input(31, "BACKTEST STOP DAY", minval=1, maxval=31)
testPeriodStop = timestamp(testStopYear, testStopMonth, testStopDay, 0, 0)

testPeriod = time >= testPeriodStart and time <= testPeriodStop ? true : false

strategy.entry("Long", strategy.long, when = longCondition0 and testPeriod)
strategy.entry("Short", strategy.short, when = shortCondition0 and testPeriod)


Thêm nữa