Chiến lược xu hướng động đa trung bình là một chiến lược giao dịch định lượng sử dụng nhiều loại chỉ số trung bình động để xác định xu hướng thị trường và điều chỉnh động vị trí đường dừng lỗ. Bằng cách kết hợp các đường trung bình động khác nhau, chiến lược này có thể đánh giá toàn diện và chính xác hơn xu hướng thị trường và đạt được giao dịch tỷ lệ thắng cao.
Chiến lược này chủ yếu thực hiện 8 loại trung bình chuyển động khác nhau thông qua các hàm tùy chỉnh, bao gồm Trung bình chuyển động đơn giản (SMA), Trung bình chuyển động nhân tố (EMA), Trung bình chuyển động cân (WMA), Trung bình chuyển động tam giác (TMA), Trung bình động biến chỉ số (VIDYA), Trung bình chuyển động Wilder
Chiến lược đầu tiên tính toán loại trung bình động đã chọn, và sau đó tính toán động vị trí của đường ray trên và dưới dựa trên tham số phần trăm đã đặt. Một tín hiệu mua được kích hoạt khi giá vượt qua đường ray trên, và một tín hiệu bán được kích hoạt khi giá vượt qua đường ray dưới. Ngoài ra, chiến lược cũng theo dõi các giao thoa giữa đường trung bình động và giá như các tín hiệu phán đoán phụ trợ.
Trong quá trình tính toán, chiến lược cũng đánh giá hướng của xu hướng thị trường, do đó điều chỉnh động vị trí của các đường ray trên và dưới. Cụ thể, khi một xu hướng tăng được xác định, đường ray dưới sẽ di chuyển lên sau khi giá tăng để đường dừng lỗ có thể theo dõi giá tăng tối ưu. Khi xu hướng giảm được xác định, đường ray trên sẽ di chuyển xuống sau khi giá giảm để giảm điểm dừng lỗ và giảm thiểu lỗ.
Giải pháp:
Vẫn còn nhiều chỗ để tối ưu hóa chiến lược này:
Chiến lược xu hướng động đa động trung bình xác định xu hướng thị trường bằng cách kết hợp nhiều chỉ số trung bình động, và bắt đầu giao dịch dựa trên tín hiệu đột phá giá trong khi điều chỉnh động các vị trí đường dừng lỗ để có lợi nhuận hiệu quả. Chiến lược này tích hợp thành công ba khái niệm chiến lược định lượng chính là theo xu hướng, giao dịch đột phá giá và dừng động, thể hiện sự ổn định và lợi nhuận mạnh mẽ. Với những cải tiến hơn nữa trong tối ưu hóa tham số và nhận dạng mẫu, chiến lược này cho thấy tiềm năng lớn để tiếp tục nâng cao hiệu suất, làm cho nó trở thành một chiến lược định lượng tiên tiến có giá trị cao xứng đáng với nghiên cứu và ứng dụng tập trung.
/*backtest start: 2022-11-16 00:00:00 end: 2023-11-22 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=4 // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © KivancOzbilgic //created by: @Anil_Ozeksi //developer: ANIL ÖZEKŞİ //author: @kivancozbilgic strategy("Optimized Trend Tracker","OTTEx", overlay=true) src = input(close, title="Source") length=input(2, "OTT Period", minval=1) percent=input(1.4, "OTT Percent", type=input.float, step=0.1, minval=0) showsupport = input(title="Show Support Line?", type=input.bool, defval=true) showsignalsk = input(title="Show Support Line Crossing Signals?", type=input.bool, defval=true) showsignalsc = input(title="Show Price/OTT Crossing Signals?", type=input.bool, defval=false) highlight = input(title="Show OTT Color Changes?", type=input.bool, defval=false) showsignalsr = input(title="Show OTT Color Change Signals?", type=input.bool, defval=false) highlighting = input(title="Highlighter On/Off ?", type=input.bool, defval=true) mav = input(title="Moving Average Type", defval="VAR", options=["SMA", "EMA", "WMA", "TMA", "VAR", "WWMA", "ZLEMA", "TSF"]) Var_Func(src,length)=> valpha=2/(length+1) vud1=src>src[1] ? src-src[1] : 0 vdd1=src<src[1] ? src[1]-src : 0 vUD=sum(vud1,9) vDD=sum(vdd1,9) vCMO=nz((vUD-vDD)/(vUD+vDD)) VAR=0.0 VAR:=nz(valpha*abs(vCMO)*src)+(1-valpha*abs(vCMO))*nz(VAR[1]) VAR=Var_Func(src,length) Wwma_Func(src,length)=> wwalpha = 1/ length WWMA = 0.0 WWMA := wwalpha*src + (1-wwalpha)*nz(WWMA[1]) WWMA=Wwma_Func(src,length) Zlema_Func(src,length)=> zxLag = length/2==round(length/2) ? length/2 : (length - 1) / 2 zxEMAData = (src + (src - src[zxLag])) ZLEMA = ema(zxEMAData, length) ZLEMA=Zlema_Func(src,length) Tsf_Func(src,length)=> lrc = linreg(src, length, 0) lrc1 = linreg(src,length,1) lrs = (lrc-lrc1) TSF = linreg(src, length, 0)+lrs TSF=Tsf_Func(src,length) getMA(src, length) => ma = 0.0 if mav == "SMA" ma := sma(src, length) ma if mav == "EMA" ma := ema(src, length) ma if mav == "WMA" ma := wma(src, length) ma if mav == "TMA" ma := sma(sma(src, ceil(length / 2)), floor(length / 2) + 1) ma if mav == "VAR" ma := VAR ma if mav == "WWMA" ma := WWMA ma if mav == "ZLEMA" ma := ZLEMA ma if mav == "TSF" ma := TSF ma ma MAvg=getMA(src, length) fark=MAvg*percent*0.01 longStop = MAvg - fark longStopPrev = nz(longStop[1], longStop) longStop := MAvg > longStopPrev ? max(longStop, longStopPrev) : longStop shortStop = MAvg + fark shortStopPrev = nz(shortStop[1], shortStop) shortStop := MAvg < shortStopPrev ? min(shortStop, shortStopPrev) : shortStop dir = 1 dir := nz(dir[1], dir) dir := dir == -1 and MAvg > shortStopPrev ? 1 : dir == 1 and MAvg < longStopPrev ? -1 : dir MT = dir==1 ? longStop: shortStop OTT=MAvg>MT ? MT*(200+percent)/200 : MT*(200-percent)/200 plot(showsupport ? MAvg : na, color=#0585E1, linewidth=2, title="Support Line") OTTC = highlight ? OTT[2] > OTT[3] ? color.green : color.red : #B800D9 pALL=plot(nz(OTT[2]), color=OTTC, linewidth=2, title="OTT", transp=0) alertcondition(cross(OTT[2], OTT[3]), title="Color ALARM", message="OTT Has Changed Color!") alertcondition(crossover(OTT[2], OTT[3]), title="GREEN ALERT", message="OTT GREEN BUY SIGNAL!") alertcondition(crossunder(OTT[2], OTT[3]), title="RED ALERT", message="OTT RED SELL SIGNAL!") alertcondition(cross(MAvg, OTT[2]), title="Cross Alert", message="OTT - Support Line Crossing!") alertcondition(crossover(MAvg, OTT[2]), title="Crossover Alarm", message="Support Line BUY SIGNAL!") alertcondition(crossunder(MAvg, OTT[2]), title="Crossunder Alarm", message="Support Line SELL SIGNAL!") alertcondition(cross(src, OTT[2]), title="Price Cross Alert", message="OTT - Price Crossing!") alertcondition(crossover(src, OTT[2]), title="Price Crossover Alarm", message="PRICE OVER OTT - BUY SIGNAL!") alertcondition(crossunder(src, OTT[2]), title="Price Crossunder Alarm", message="PRICE UNDER OTT - SELL SIGNAL!") buySignalk = crossover(MAvg, OTT[2]) plotshape(buySignalk and showsignalsk ? OTT*0.995 : na, title="Buy", text="Buy", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white, transp=0) sellSignallk = crossunder(MAvg, OTT[2]) plotshape(sellSignallk and showsignalsk ? OTT*1.005 : na, title="Sell", text="Sell", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white, transp=0) buySignalc = crossover(src, OTT[2]) plotshape(buySignalc and showsignalsc ? OTT*0.995 : na, title="Buy", text="Buy", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white, transp=0) sellSignallc = crossunder(src, OTT[2]) plotshape(sellSignallc and showsignalsc ? OTT*1.005 : na, title="Sell", text="Sell", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white, transp=0) mPlot = plot(ohlc4, title="", style=plot.style_circles, linewidth=0,display=display.none) longFillColor = highlighting ? (MAvg>OTT ? color.green : na) : na shortFillColor = highlighting ? (MAvg<OTT ? color.red : na) : na fill(mPlot, pALL, title="UpTrend Highligter", color=longFillColor) fill(mPlot, pALL, title="DownTrend Highligter", color=shortFillColor) buySignalr = crossover(OTT[2], OTT[3]) plotshape(buySignalr and showsignalsr ? OTT*0.995 : na, title="Buy", text="Buy", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white, transp=0) sellSignallr = crossunder(OTT[2], OTT[3]) plotshape(sellSignallr and showsignalsr ? OTT*1.005 : na, title="Sell", text="Sell", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white, transp=0) showscr = input(true, title="Show Screener Label") posX_scr = input(20, title="Pos. Label x-axis") posY_scr = input(1, title="Pos. Size Label y-axis") colinput = input(title="Label Color", defval="Blue", options=["White", "Black", "Red", "Green", "Yellow", "Blue"]) col = color.gray if colinput=="White" col:=color.white if colinput=="Black" col:=color.black if colinput=="Red" col:=color.red if colinput=="Green" col:=color.green if colinput=="Yellow" col:=color.yellow if colinput=="Blue" col:=color.blue dummy0 = input(true, title = "=Backtest Inputs=") FromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31) FromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12) FromYear = input(defval = 2005, title = "From Year", minval = 2005) ToDay = input(defval = 1, title = "To Day", minval = 1, maxval = 31) ToMonth = input(defval = 1, title = "To Month", minval = 1, maxval = 12) ToYear = input(defval = 9999, title = "To Year", minval = 2006) Start = timestamp(FromYear, FromMonth, FromDay, 00, 00) Finish = timestamp(ToYear, ToMonth, ToDay, 23, 59) Timerange() => true if buySignalk strategy.entry("Long", strategy.long,when=Timerange()) if sellSignallk strategy.entry("Short", strategy.short,when=Timerange()) // t1=input('EURUSD', title='Symbol 01',type=input.symbol) // t2=input('XAUUSD', title='Symbol 02',type=input.symbol) // t3=input('AMZN', title='Symbol 03',type=input.symbol) // t4=input('TSLA', title='Symbol 04',type=input.symbol) // t5=input('BTCUSDT', title='Symbol 05',type=input.symbol) // t6=input('ETHBTC', title='Symbol 06',type=input.symbol) // t7=input('XBTUSD', title='Symbol 07',type=input.symbol) // t8=input('XRPBTC', title='Symbol 08',type=input.symbol) // t9=input('THYAO', title='Symbol 09',type=input.symbol) // t10=input('GARAN', title='Symbol 10',type=input.symbol) // t11=input('', title='Symbol 11',type=input.symbol) // t12=input('', title='Symbol 12',type=input.symbol) // t13=input('', title='Symbol 13',type=input.symbol) // t14=input('', title='Symbol 14',type=input.symbol) // t15=input('', title='Symbol 15',type=input.symbol) // t16=input('', title='Symbol 16',type=input.symbol) // t17=input('', title='Symbol 17',type=input.symbol) // t18=input('', title='Symbol 18',type=input.symbol) // t19=input('', title='Symbol 19',type=input.symbol) // t20=input('', title='Symbol 20',type=input.symbol) // OTTs(percent, length) => // Up=MAvg-MAvg*percent*0.01 // Dn=MAvg+MAvg*percent*0.01 // TrendUp = 0.0 // TrendUp := MAvg[1]>TrendUp[1] ? max(Up,TrendUp[1]) : Up // TrendDown = 0.0 // TrendDown := MAvg[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn // Trend = 0.0 // Trend := MAvg > TrendDown[1] ? 1: MAvg< TrendUp[1]? -1: nz(Trend[1],1) // Tsl = Trend==1? TrendUp: TrendDown // S_Buy = Trend == 1 ? 1 : 0 // S_Sell = Trend != 1 ? 1 : 0 // [Trend, Tsl] // [Trend, Tsl] = OTTs(percent, length) // TrendReversal = Trend != Trend[1] // [t01, s01] = security(t1, timeframe.period, OTTs(percent, length)) // [t02, s02] = security(t2, timeframe.period, OTTs(percent, length)) // [t03, s03] = security(t3, timeframe.period, OTTs(percent, length)) // [t04, s04] = security(t4, timeframe.period, OTTs(percent, length)) // [t05, s05] = security(t5, timeframe.period, OTTs(percent, length)) // [t06, s06] = security(t6, timeframe.period, OTTs(percent, length)) // [t07, s07] = security(t7, timeframe.period, OTTs(percent, length)) // [t08, s08] = security(t8, timeframe.period, OTTs(percent, length)) // [t09, s09] = security(t9, timeframe.period, OTTs(percent, length)) // [t010, s010] = security(t10, timeframe.period, OTTs(percent, length)) // [t011, s011] = security(t11, timeframe.period, OTTs(percent, length)) // [t012, s012] = security(t12, timeframe.period, OTTs(percent, length)) // [t013, s013] = security(t13, timeframe.period, OTTs(percent, length)) // [t014, s014] = security(t14, timeframe.period, OTTs(percent, length)) // [t015, s015] = security(t15, timeframe.period, OTTs(percent, length)) // [t016, s016] = security(t16, timeframe.period, OTTs(percent, length)) // [t017, s017] = security(t17, timeframe.period, OTTs(percent, length)) // [t018, s018] = security(t18, timeframe.period, OTTs(percent, length)) // [t019, s019] = security(t19, timeframe.period, OTTs(percent, length)) // [t020, s020] = security(t20, timeframe.period, OTTs(percent, length)) // tr01 = t01 != t01[1], up01 = t01 == 1, dn01 = t01 == -1 // tr02 = t02 != t02[1], up02 = t02 == 1, dn02 = t02 == -1 // tr03 = t03 != t03[1], up03 = t03 == 1, dn03 = t03 == -1 // tr04 = t04 != t04[1], up04 = t04 == 1, dn04 = t04 == -1 // tr05 = t05 != t05[1], up05 = t05 == 1, dn05 = t05 == -1 // tr06 = t06 != t06[1], up06 = t06 == 1, dn06 = t06 == -1 // tr07 = t07 != t07[1], up07 = t07 == 1, dn07 = t07 == -1 // tr08 = t08 != t08[1], up08 = t08 == 1, dn08 = t08 == -1 // tr09 = t09 != t09[1], up09 = t09 == 1, dn09 = t09 == -1 // tr010 = t010 != t010[1], up010 = t010 == 1, dn010 = t010 == -1 // tr011 = t011 != t011[1], up011 = t011 == 1, dn011 = t011 == -1 // tr012 = t012 != t012[1], up012 = t012 == 1, dn012 = t012 == -1 // tr013 = t013 != t013[1], up013 = t013 == 1, dn013 = t013 == -1 // tr014 = t014 != t014[1], up014 = t014 == 1, dn014 = t014 == -1 // tr015 = t015 != t015[1], up015 = t015 == 1, dn015 = t015 == -1 // tr016 = t016 != t016[1], up016 = t016 == 1, dn016 = t016 == -1 // tr017 = t017 != t017[1], up017 = t017 == 1, dn017 = t017 == -1 // tr018 = t018 != t018[1], up018 = t018 == 1, dn018 = t018 == -1 // tr019 = t019 != t019[1], up019 = t019 == 1, dn019 = t019 == -1 // tr020 = t020 != t020[1], up020 = t020 == 1, dn020 = t020 == -1 // pot_label = 'Potential Reversal: \n' // pot_label := tr01 ? pot_label + t1 + '\n' : pot_label // pot_label := tr02 ? pot_label + t2 + '\n' : pot_label // pot_label := tr03 ? pot_label + t3 + '\n' : pot_label // pot_label := tr04 ? pot_label + t4 + '\n' : pot_label // pot_label := tr05 ? pot_label + t5 + '\n' : pot_label // pot_label := tr06 ? pot_label + t6 + '\n' : pot_label // pot_label := tr07 ? pot_label + t7 + '\n' : pot_label // pot_label := tr08 ? pot_label + t8 + '\n' : pot_label // pot_label := tr09 ? pot_label + t9 + '\n' : pot_label // pot_label := tr010 ? pot_label + t10 + '\n' : pot_label // pot_label := tr011 ? pot_label + t11 + '\n' : pot_label // pot_label := tr012 ? pot_label + t12 + '\n' : pot_label // pot_label := tr013 ? pot_label + t13 + '\n' : pot_label // pot_label := tr014 ? pot_label + t14 + '\n' : pot_label // pot_label := tr015 ? pot_label + t15 + '\n' : pot_label // pot_label := tr016 ? pot_label + t16 + '\n' : pot_label // pot_label := tr017 ? pot_label + t17 + '\n' : pot_label // pot_label := tr018 ? pot_label + t18 + '\n' : pot_label // pot_label := tr019 ? pot_label + t19 + '\n' : pot_label // pot_label := tr020 ? pot_label + t20 + '\n' : pot_label // scr_label = 'Confirmed Reversal: \n' // scr_label := tr01[1] ? scr_label + t1 + '\n' : scr_label // scr_label := tr02[1] ? scr_label + t2 + '\n' : scr_label // scr_label := tr03[1] ? scr_label + t3 + '\n' : scr_label // scr_label := tr04[1] ? scr_label + t4 + '\n' : scr_label // scr_label := tr05[1] ? scr_label + t5 + '\n' : scr_label // scr_label := tr06[1] ? scr_label + t6 + '\n' : scr_label // scr_label := tr07[1] ? scr_label + t7 + '\n' : scr_label // scr_label := tr08[1] ? scr_label + t8 + '\n' : scr_label // scr_label := tr09[1] ? scr_label + t9 + '\n' : scr_label // scr_label := tr010[1] ? scr_label + t10 + '\n' : scr_label // scr_label := tr011[1] ? scr_label + t11 + '\n' : scr_label // scr_label := tr012[1] ? scr_label + t12 + '\n' : scr_label // scr_label := tr013[1] ? scr_label + t13 + '\n' : scr_label // scr_label := tr014[1] ? scr_label + t14 + '\n' : scr_label // scr_label := tr015[1] ? scr_label + t15 + '\n' : scr_label // scr_label := tr016[1] ? scr_label + t16 + '\n' : scr_label // scr_label := tr017[1] ? scr_label + t17 + '\n' : scr_label // scr_label := tr018[1] ? scr_label + t18 + '\n' : scr_label // scr_label := tr019[1] ? scr_label + t19 + '\n' : scr_label // scr_label := tr020[1] ? scr_label + t20 + '\n' : scr_label // up_label = 'Uptrend: \n' // up_label := up01[1] ? up_label + t1 + '\n' : up_label // up_label := up02[1] ? up_label + t2 + '\n' : up_label // up_label := up03[1] ? up_label + t3 + '\n' : up_label // up_label := up04[1] ? up_label + t4 + '\n' : up_label // up_label := up05[1] ? up_label + t5 + '\n' : up_label // up_label := up06[1] ? up_label + t6 + '\n' : up_label // up_label := up07[1] ? up_label + t7 + '\n' : up_label // up_label := up08[1] ? up_label + t8 + '\n' : up_label // up_label := up09[1] ? up_label + t9 + '\n' : up_label // up_label := up010[1] ? up_label + t10 + '\n' : up_label // up_label := up011[1] ? up_label + t11 + '\n' : up_label // up_label := up012[1] ? up_label + t12 + '\n' : up_label // up_label := up013[1] ? up_label + t13 + '\n' : up_label // up_label := up014[1] ? up_label + t14 + '\n' : up_label // up_label := up015[1] ? up_label + t15 + '\n' : up_label // up_label := up016[1] ? up_label + t16 + '\n' : up_label // up_label := up017[1] ? up_label + t17 + '\n' : up_label // up_label := up018[1] ? up_label + t18 + '\n' : up_label // up_label := up019[1] ? up_label + t19 + '\n' : up_label // up_label := up020[1] ? up_label + t20 + '\n' : up_label // dn_label = 'Downtrend: \n' // dn_label := dn01[1] ? dn_label + t1 + '\n' : dn_label // dn_label := dn02[1] ? dn_label + t2 + '\n' : dn_label // dn_label := dn03[1] ? dn_label + t3 + '\n' : dn_label // dn_label := dn04[1] ? dn_label + t4 + '\n' : dn_label // dn_label := dn05[1] ? dn_label + t5 + '\n' : dn_label // dn_label := dn06[1] ? dn_label + t6 + '\n' : dn_label // dn_label := dn07[1] ? dn_label + t7 + '\n' : dn_label // dn_label := dn08[1] ? dn_label + t8 + '\n' : dn_label // dn_label := dn09[1] ? dn_label + t9 + '\n' : dn_label // dn_label := dn010[1] ? dn_label + t10 + '\n' : dn_label // dn_label := dn011[1] ? dn_label + t11 + '\n' : dn_label // dn_label := dn012[1] ? dn_label + t12 + '\n' : dn_label // dn_label := dn013[1] ? dn_label + t13 + '\n' : dn_label // dn_label := dn014[1] ? dn_label + t14 + '\n' : dn_label // dn_label := dn015[1] ? dn_label + t15 + '\n' : dn_label // dn_label := dn016[1] ? dn_label + t16 + '\n' : dn_label // dn_label := dn017[1] ? dn_label + t17 + '\n' : dn_label // dn_label := dn018[1] ? dn_label + t18 + '\n' : dn_label // dn_label := dn019[1] ? dn_label + t19 + '\n' : dn_label // dn_label := dn020[1] ? dn_label + t20 + '\n' : dn_label // f_colorscr (_valscr ) => // _valscr ? #00000000 : na // f_printscr (_txtscr ) => // var _lblscr = label(na), // label.delete(_lblscr ), // _lblscr := label.new( // time + (time-time[1])*posX_scr , // ohlc4[posY_scr], // _txtscr , // xloc.bar_time, // yloc.price, // f_colorscr ( showscr ), // textcolor = showscr ? col : na, // size = size.normal, // style=label.style_label_center // ) // f_printscr ( scr_label + '\n' + pot_label +'\n' + up_label + '\n' + dn_label)