Ini adalah strategi berdasarkan momentum yang menggunakan penunjuk pengayun seperti RSI, Stoch, MACD untuk menjana isyarat perdagangan. Idea utama adalah untuk mengenal pasti arah trend apabila harga berayun dengan menggunakan penunjuk dan memasuki perdagangan berdasarkan isyarat penunjuk. Strategi ini juga menggunakan supertrend tertunda untuk stop loss.
Strategi pertama memanggil fungsi tersuai f_getOscilatorValues untuk mendapatkan nilai penunjuk osilator yang berbeza termasuk RSI, Stoch, MACD dan lain-lain Kemudian ia mengira nilai supertrend tertunda dengan f_getSupertrend untuk mengesan stop loss.
Selepas mengira penunjuk, strategi memanggil f_getBuySellStops untuk mengira hentian masuk dan sasaran keuntungan berdasarkan nilai penunjuk. Khususnya, ia mengira ATR dan menggunakan ATR dikalikan dengan pekali hentian kerugian sebagai hentian masuk, dan ATR dikalikan dengan pekali mengambil keuntungan sebagai sasaran keuntungan. Hentian dan sasaran akan disesuaikan apabila trend berbalik.
Seterusnya, strategi menentukan arah lilin. Lilin uptrend berwarna hijau dan lilin downtrend berwarna merah. Selepas merangka lilin dan penunjuk, strategi memeriksa sama ada syarat kemasukan dipenuhi. Syarat kemasukan adalah membeli apabila penunjuk menunjukkan overbought dan harga pecah di atas band atas, dan menjual apabila penunjuk menunjukkan oversold dan harga pecah di bawah band bawah.
Selepas masuk, stop loss diikuti oleh band atas/bawah mana yang lebih dekat. Apabila stop loss dicetuskan, kedudukan ditutup. Apabila harga mencapai sasaran keuntungan, keuntungan separa diambil.
Kelebihan strategi ini ialah:
Menggunakan pengayun untuk mengenal pasti arah trend boleh menangkap peluang pembalikan jangka pendek tepat pada masanya.
Menggunakan stop loss supertrend yang ditangguhkan boleh berhenti sebelum kerugian meningkat, mengehadkan kerugian perdagangan tunggal.
Mengira sasaran stop loss dan keuntungan berdasarkan ATR dinamik membantu menyesuaikan saiz kedudukan.
Penapisan dengan purata bergerak jangka masa yang lebih tinggi mengelakkan terperangkap dalam penyatuan.
Mengambil keuntungan separa membolehkan keuntungan berjalan sambil mengunci beberapa keuntungan.
Logiknya mudah dan mudah difahami untuk pemula perdagangan kuant.
Beberapa risiko strategi ini termasuk:
Osilator mungkin mempunyai masalah yang tertinggal, menyebabkan isyarat kemasukan yang tertunda dan isyarat keluar yang lebih awal. Ini boleh ditingkatkan dengan mengoptimumkan parameter atau menambah penunjuk trend berikut.
Julat stop loss yang ketat boleh dipukul. Julat stop loss boleh diperluas atau berhenti dinamik seperti Chandelier boleh digunakan.
Posisi yang tersisa selepas mengambil keuntungan separa boleh dihentikan.
Backtest risiko terlalu sesuai. Strategi harus disahkan di pasaran yang berbeza.
Kegagalan penapis purata bergerak jangka masa yang lebih tinggi.
Strategi ini boleh dioptimumkan dalam aspek berikut:
Uji kombinasi parameter osilator yang berbeza dan cari yang memberikan isyarat berkualiti.
Cuba menggantikan mengambil keuntungan separa dengan penangguhan keuntungan yang berdasarkan ATR atau purata bergerak.
Tambah algoritma pembelajaran mesin untuk menggantikan purata bergerak untuk analisis trend dan meningkatkan ketepatan.
Tambahkan penunjuk jumlah sebagai keadaan penapisan untuk mengelakkan pembalikan yang tidak perlu.
Mengumpulkan dan beratkan penunjuk optimum untuk mencari kombinasi optimum untuk aset.
Tambah modul kawalan risiko pembelajaran mesin untuk mengoptimumkan berhenti, sasaran dan saiz kedudukan secara dinamik.
Menggabungkan arbitrage segitiga atau isyarat perdagangan asas menggunakan perbezaan harga antara niaga hadapan dan spot.
Secara keseluruhan ini adalah strategi yang hebat untuk pemula perdagangan kuant dengan logika yang jelas yang memberi tumpuan kepada penunjuk dan pengurusan risiko. Tetapi pengoptimuman parameter dan pengurangan risiko masih diperlukan untuk perdagangan langsung. Ia juga boleh ditingkatkan dalam aspek seperti analisis trend, pengoptimuman stop loss, model ensemble dll untuk meningkatkan ketahanan. Sebagai templat strategi perdagangan, ia memberikan rujukan yang berharga.
/*backtest start: 2023-08-26 00:00:00 end: 2023-09-25 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/ // © HeWhoMustNotBeNamed //@version=4 strategy("Oscilator candles - strategy", overlay=false, initial_capital = 1000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, pyramiding = 1, commission_value = 0.01, calc_on_order_fills = true) oscilatorType = input(title="Oscliator Type", defval="stoch", options=["rsi", "stoch", "cog", "macd", "tsi", "cci", "cmo", "mfi"]) length = input(3) shortlength = input(3) longlength = input(9) showSupertrend = input(true) AtrMAType = input(title="Moving Average Type", defval="rma", options=["ema", "sma", "hma", "rma", "vwma", "wma"]) AtrLength = input(30, step=10) stopMultiplier = input(4) targetMultiplier = input(3) wicks = input(true) considerWicksForDelayByStep = input(false) colorByPreviousClose = input(true) useHTFPivot = input(false) resolution = input("12M", type=input.resolution) HTFMultiplier = input(4, title="Higher Timeframe multiplier (Used when resolution is set to Same as Symbol)", minval=2, step=1) PivotLength = input(2, step=1) tradeDirection = input(title="Trade Direction", defval=strategy.direction.long, options=[strategy.direction.all, strategy.direction.long, strategy.direction.short]) i_startTime = input(defval = timestamp("01 Jan 2010 00:00 +0000"), title = "Backtest Start Time", type = input.time) i_endTime = input(defval = timestamp("01 Jan 2099 00:00 +0000"), title = "Backtest End Time", type = input.time) inDateRange = true f_getOscilatorValues(oscilatorType, length, shortlength, longlength)=> oOpen = rsi(open, length) oClose = rsi(close, length) oHigh = rsi(high, length) oLow = rsi(low, length) if(oscilatorType == "tsi") oOpen := tsi(open, shortlength, longlength) oClose := tsi(close, shortlength, longlength) oHigh := tsi(high, shortlength, longlength) oLow := tsi(low, shortlength, longlength) if(oscilatorType == "stoch") oOpen := stoch(open, longlength, shortlength, length) oClose := stoch(close, longlength, shortlength, length) oHigh := stoch(high, longlength, shortlength, length) oLow := stoch(low, longlength, shortlength, length) if(oscilatorType == "cci") oOpen := cci(open, length) oClose := cci(close, length) oHigh := cci(high, length) oLow := cci(low, length) if(oscilatorType == "cog") oOpen := cog(open, length) oClose := cog(close, length) oHigh := cog(high, length) oLow := cog(low, length) if(oscilatorType == "cmo") oOpen := cmo(open, length) oClose := cmo(close, length) oHigh := cmo(high, length) oLow := cmo(low, length) if(oscilatorType == "mfi") oOpen := mfi(open, length) oClose := mfi(close, length) oHigh := mfi(high, length) oLow := mfi(low, length) if(oscilatorType == "macd") [macdLineOpen, signalLineOpen, histLineOpen] = macd(open, shortlength, longlength, length) [macdLineClose, signalLineClose, histLineClose] = macd(close, shortlength, longlength, length) [macdLineHigh, signalLineHigh, histLineHigh] = macd(high, shortlength, longlength, length) [macdLineLow, signalLineLow, histLineLow] = macd(low, shortlength, longlength, length) oOpen := macdLineOpen oClose := macdLineClose oHigh := macdLineHigh oLow := macdLineLow [oOpen, oClose, oHigh, oLow] f_getMovingAverage(source, MAType, length)=> ma = sma(source, length) if(MAType == "ema") ma := ema(source,length) if(MAType == "hma") ma := hma(source,length) if(MAType == "rma") ma := rma(source,length) if(MAType == "vwma") ma := vwma(source,length) if(MAType == "wma") ma := wma(source,length) ma f_getSupertrend(oOpen, oClose, oHigh, oLow, AtrMAType, AtrLength, stopMultiplier, wicks)=> truerange = max(oHigh, oClose[1]) - min(oLow, oClose[1]) averagetruerange = f_getMovingAverage(truerange, AtrMAType, AtrLength) atr = averagetruerange * stopMultiplier longStop = oClose - atr longStopPrev = nz(longStop[1], longStop) longStop := (wicks ? oLow[1] : oClose[1]) > longStopPrev ? max(longStop, longStopPrev) : longStop shortStop = oClose + atr shortStopPrev = nz(shortStop[1], shortStop) shortStop := (wicks ? oHigh[1] : oClose[1]) < shortStopPrev ? min(shortStop, shortStopPrev) : shortStop dir = 1 dir := nz(dir[1], dir) dir := dir == -1 and (wicks ? oHigh : oClose) > shortStopPrev ? 1 : dir == 1 and (wicks ? oLow : oClose) < longStopPrev ? -1 : dir trailingStop = dir == 1? longStop : shortStop [dir, trailingStop] f_getBuySellStops(oOpen, oClose, oHigh, oLow, AtrMAType, AtrLength, considerWicks, considerWicksForDelayByStep, stopMultiplier, targetMultiplier)=> barState = 0 source = oClose truerange = max(oHigh, oClose[1]) - min(oLow, oClose[1]) atr = f_getMovingAverage(truerange, AtrMAType, AtrLength) buyStop = source - atr * stopMultiplier sellStop = source + atr * stopMultiplier buyStopDerived = buyStop sellStopDerived = sellStop highTarget = considerWicks ? oHigh : source lowTarget = considerWicks ? oLow : source highTargetDelayByStep = considerWicksForDelayByStep ? oHigh : source lowTargetDelayByStep = considerWicksForDelayByStep ? oLow : source barState := highTarget > sellStopDerived[1] ? 1 : lowTarget < buyStopDerived[1] ? -1 : nz(barState[1],0) buyMultiplier = (barState == 1)? stopMultiplier : targetMultiplier sellMultiplier = (barState == -1)? stopMultiplier : targetMultiplier buyStop := source - atr * buyMultiplier sellStop := source + atr * sellMultiplier buyStop := barState == 1? max(buyStop, buyStop[1]) : barState == -1? min(buyStop, buyStop[1]) : buyStop sellStop := barState == 1? max(sellStop, sellStop[1]) : barState == -1? min(sellStop, sellStop[1]) : sellStop buyStopDerived := buyStop sellStopDerived := sellStop buyStopDerived := highTargetDelayByStep < sellStopDerived[1] and lowTargetDelayByStep > buyStopDerived[1] ? buyStopDerived[1] : buyStopDerived sellStopDerived := highTargetDelayByStep < sellStopDerived[1] and lowTargetDelayByStep > buyStopDerived[1] ? sellStopDerived[1] : sellStopDerived [buyStopDerived, sellStopDerived, barState] f_secureSecurity(_symbol, _res, _src) => security(_symbol, _res, _src[1], lookahead = barmerge.lookahead_on, gaps=barmerge.gaps_off) f_multiple_resolution(HTFMultiplier) => target_Res_In_Min = timeframe.multiplier * HTFMultiplier * ( timeframe.isseconds ? 1. / 60. : timeframe.isminutes ? 1. : timeframe.isdaily ? 1440. : timeframe.isweekly ? 7. * 24. * 60. : timeframe.ismonthly ? 30.417 * 24. * 60. : na) target_Res_In_Min <= 0.0417 ? "1S" : target_Res_In_Min <= 0.167 ? "5S" : target_Res_In_Min <= 0.376 ? "15S" : target_Res_In_Min <= 0.751 ? "30S" : target_Res_In_Min <= 1440 ? tostring(round(target_Res_In_Min)) : tostring(round(min(target_Res_In_Min / 1440, 365))) + "D" f_getPivotHighLow(oOpen, oClose, oHigh, oLow, HTFMultiplier, resolution, PivotLength)=> derivedResolution = resolution == ""? f_multiple_resolution(HTFMultiplier) : resolution HTFHigh = f_secureSecurity(syminfo.tickerid, derivedResolution, oHigh) HTFLow = f_secureSecurity(syminfo.tickerid, derivedResolution, oLow) CLOSEprev = f_secureSecurity(syminfo.tickerid, derivedResolution, oClose) pivothi = pivothigh(HTFHigh, PivotLength, PivotLength) pivotlo = pivotlow(HTFLow, PivotLength, PivotLength) pivothi := na(pivothi)? nz(pivothi[1]) : pivothi pivotlo := na(pivotlo)? nz(pivotlo[1]) : pivotlo [pivothi, pivotlo] [oOpen, oClose, oHigh, oLow] = f_getOscilatorValues(oscilatorType, length, shortlength, longlength) [dir, trailingStop] = f_getSupertrend(oOpen, oClose, oHigh, oLow, AtrMAType, AtrLength, stopMultiplier, wicks) candleColor = colorByPreviousClose ? (oClose[1] < oClose ? color.green : oClose[1] > oClose ? color.red : color.silver) : (oOpen < oClose ? color.green : oOpen > oClose ? color.red : color.silver) plotcandle(oOpen, oHigh, oLow, oClose, 'Oscilator Candles', color = candleColor) [buyStopDerived, sellStopDerived, barState] = f_getBuySellStops(oOpen, oClose, oHigh, oLow, AtrMAType, AtrLength, wicks, considerWicksForDelayByStep, stopMultiplier, targetMultiplier) trailingStopDerived = barState == 1? buyStopDerived : sellStopDerived plot(showSupertrend?trailingStopDerived:na, title="TrailingStop", style=plot.style_linebr, linewidth=1, color= barState == 1 ? color.green : color.red) [pivotHigh, pivotLow] = f_getPivotHighLow(open, close, high, low, HTFMultiplier, resolution, PivotLength) buyCondition = (barState == 1) and (close > pivotHigh or not useHTFPivot) exitBuyConditin = (barState == -1) sellCondition = (barState == -1) and (close < pivotLow or not useHTFPivot) exitSellCondition = (barState == 1) // strategy.risk.allow_entry_in(tradeDirection) strategy.entry("Buy", strategy.long, when=buyCondition and inDateRange, oca_name="oca") strategy.entry("Sell", strategy.short, when=sellCondition and inDateRange, oca_name="oca") strategy.close("Buy", when = exitBuyConditin) strategy.close( "Sell", when = exitSellCondition)