
Idea utama strategi ini adalah untuk menggunakan penembusan garis rata-rata peringkat tinggi untuk mencapai perdagangan trend. Dalam jangka masa peringkat tinggi, apabila harga menembusi naik atau turun dari garis rata-rata, permulaan trend dapat difahami, dan arah yang sesuai dapat dipilih untuk diikuti.
Strategi ini dibangunkan menggunakan bahasa Pine Script dan terdiri daripada beberapa bahagian:
Mendefinisikan parameter tempoh purata, dengan nilai lalai 200; mendefinisikan parameter tempoh masa K, dengan nilai lalai āDā
Menggunakan fungsi ta.ema untuk mengira Exponential Moving Average.
Gunakan fungsi ta.crossover dan ta.crossunder untuk menentukan sama ada harga menembusi atau di bawah garis purata.
Apabila berlaku penembusan, gambarkan anak panah ke atas atau ke bawah pada garis K.
Apabila berlaku penembusan, pilih arah untuk membuka kedudukan, dan tutup kedudukan selepas jarak berhenti dua kali ganda dicapai.
Strategi ini bergantung kepada kebolehan menilai trend pada paras rata-rata peringkat tinggi, dan untuk menjejaki trend melalui operasi terobosan yang mudah, ia adalah strategi yang lebih tradisional.
Strategi ini mempunyai beberapa kelebihan:
Konsepnya mudah, mudah difahami dan difahami.
Dengan hanya bergantung pada satu indikator garis rata, parameter mudah disesuaikan.
Ia boleh menjadi trend, dan ia tidak akan sering diperdagangkan.
Siklus peringkat tinggi menunjukkan trend besar dengan jelas dan tidak mudah dipengaruhi oleh turun naik jangka pendek.
Kombinasi kitaran masa yang berbeza boleh dikonfigurasi, sesuai dengan pelbagai jenis.
Ia boleh dijumpai dengan mudah dalam pelbagai varieti dan sukar untuk dikurung pada masa yang sama.
Strategi ini mempunyai beberapa risiko:
Sinyal penembusan boleh menyebabkan penembusan palsu yang tidak dapat menyaring pergerakan pasaran dengan berkesan.
Tidak dapat memanfaatkan peluang untuk mendapatkan keuntungan daripada talian pendek.
Dalam kes ini, orang ramai boleh membuat keputusan yang tidak tepat, tetapi ia boleh menyebabkan kerugian yang lebih besar.
Apabila kitaran garis purata dan kitaran dagangan tidak sepadan, ia boleh menyebabkan terlalu banyak dagangan atau kerugian.
Tidak boleh menghentikan kerugian dalam masa nyata, kemungkinan besar kerugian akan meningkat.
Penyelesaian untuk menghadapi risiko termasuk: menggabungkan indikator trend, menambah syarat penapisan, memendekkan tempoh pemegang kedudukan dengan sewajarnya, menyesuaikan kedudukan hentian secara dinamik, dan sebagainya.
Strategi ini boleh dipertimbangkan untuk dioptimumkan dalam beberapa aspek:
Menambah kombinasi penunjuk trend seperti MACD, KD dan lain-lain untuk meningkatkan kebolehpercayaan penembusan.
Meningkatkan syarat penapisan seperti jumlah transaksi atau saluran Blink untuk mengelakkan penembusan palsu.
Optimumkan padanan kitaran parameter untuk menjadikan kitaran pegangan lebih sesuai dengan kitaran trend.
Menambah strategi berhenti kehilangan dalam masa nyata untuk mengawal kerugian tunggal dengan menjejaki berhenti kehilangan.
Pertimbangkan untuk mengoptimumkan parameter secara dinamik dengan menggabungkan teknologi pembelajaran mesin.
Mencuba pelbagai jenis portfolio aset untuk meningkatkan kestabilan keseluruhan.
Strategi ini secara keseluruhan agak mudah dan praktikal, untuk mencapai trend pelacakan dengan simpulan garis rata, mudah dikuasai, boleh menjadi salah satu strategi permulaan perdagangan kuantitatif. Tetapi ada beberapa masalah, yang perlu diperbaiki melalui indikator gabungan, parameter pengoptimuman, dan stop loss dinamik, untuk menjadikan strategi lebih stabil dan berkesan.
/*backtest
start: 2023-09-29 00:00:00
end: 2023-10-29 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// @version=5
// Open-Range-Breakout strategy
// No license. Free and Open Source.
strategy('Strategy: ORB', shorttitle="ORB", overlay=true , currency=currency.NONE, initial_capital=100000)
// Inputs
period = input.int(defval=15, title="TimeRange", tooltip="The range in minutes (default: 15m)")
sessionInput = input(defval="0915-0930", title="Time Range", group="ORB settings", tooltip='What is the timeperiod (default 9:15AM to 9:30AM, exchange timezone')
hide = input.bool(defval = false, title="Hide ORB Range", group="ORB setting", tooltip = 'Hide the ORB range drawing')
// SL Related
slAtrLen = input.int(defval=14, title="ATR Period for placing SL", group="StopLoss settings")
showSLLines = input.bool(defval=false, title="Show SL lines in chart", tooltip="Show SL lines also as dotted lines in chart. Note: chart may look untidy.", group="StopLoss settings")
// Further Filtering
ignoreMementumVolume = input.bool(defval=false, title="Ignore Momentum & Volume", tooltip="Ignore Momentum & Volume to find out trades", group="Strengh Settings")
rsiLen = input.int(defval=14, title="Momentum Period", group="Strengh Settings", tooltip = 'To determine the momentum, RSI period is set default to 100')
rsiBullish = input.int(defval=50, step=1, title="Bullish Momentum", group="Strengh Settings", tooltip = 'Bullish Momentum, default set to RSI as 50')
rsiBearish = input.int(defval=50, step=1, title="Bearish Momentum", group="Strengh Settings", tooltip = 'Bearish Momentum, default set to RSI as 50')
volAvg = input.int(defval=20, step=1, title="Volume Average Period", group="Strengh Settings", tooltip = 'To calculate average volume, how many historical bars are considered. Default: 20.')
volThreshold = input.float(defval=1, step=0.1, title="Volume Strengh", group="Strengh Settings", tooltip = 'Multiplier: How big the current bar volume compared to average of last 20')
trendPeriod = input.int(defval=200, step=1, title="Trend Period", group="Trend Settings", tooltip = 'To calculate trend, what period is considered. Default: 200.')
hideTrend = input.bool(defval = false, title="Hide the trend line", group="Trend Settings", tooltip = 'Hide the trend')
hidePDHCL = input.bool(defval = false, title="Hide the PDHCL (prev day High Close Low range)", tooltip = 'Hide the Previous Day High, Close, Low lines')
hideTable = input.bool(defval = false, title="Hide the Summary Table", tooltip = 'Hide the summary table.')
// Trade related
rrRatio = input.float(title='Risk:Reward', step=0.1, defval=2.0, group="Trade settings")
endOfDay = input.int(defval=1500, title="Close all trades, default is 3:00 PM, 1500 hours (integer)", group="Trade settings")
mktAlwaysOn = input.bool(defval=true, title="Markets that never closed (Crypto, Forex, Commodity)", tooltip="Some markers never closes. For those cases, make this checked.", group="Trade settings")
lotSize = input.int(title='Lot Size', step=1, defval=1, group="Trade settings")
// Util method
is_newbar(res) =>
timeframe.change(time(res)) != 0
// print table
printTable(txt) =>
var table t = table.new(position.bottom_right, 1, 1)
table.cell(t, 0, 0, txt, text_halign = text.align_left, bgcolor = color.lime)
// globals
t = time(timeframe.period, sessionInput + ":1234567") // everyday
in_session = not na(t)
is_first = in_session and not in_session[1]
is_end_session = in_session[1] and not in_session
green(open, close) => close > open ? true : false
red(open, close) => close < open ? true : false
var float orb_high = na
var float orb_low = na
if is_first
orb_high := high
orb_low := low
else
orb_high := orb_high[1]
orb_low := orb_low[1]
if high > orb_high and in_session
orb_high := high
if low < orb_low and in_session
orb_low := low
plot(hide ? na : orb_high, style=plot.style_line, color=orb_high[1] != orb_high ? na : color.green, title="ORB High", linewidth=2)
plot(hide ? na : orb_low, style=plot.style_line, color=orb_low[1] != orb_low ? na : color.red, title="ORB Low", linewidth=2)
// PDHCL (Previous Day High Close Low)
[dh,dl,dc] = request.security(syminfo.ticker, "D", [high[1],low[1], close[1]], lookahead=barmerge.lookahead_on)
plot(hidePDHCL ? na : dh, title="Prev High", color=color.red, linewidth=2, trackprice=true, show_last = 1)
plot(hidePDHCL ? na : dl, title="Prev Low", color=color.green, linewidth=2, trackprice=true, show_last = 1)
plot(hidePDHCL ? na : dc, title="Prev Close", color=color.black, linewidth=2, trackprice=true, show_last = 1)
plot(hidePDHCL ? na : ta.vwap(close), title="Prev VWAP", color=color.fuchsia, linewidth=2, trackprice=true, show_last = 1)
var l1 = label.new(bar_index, hidePDHCL ? na : dh, 'PDH', style=label.style_label_right)
// Previous Day WWAP
// For SL calculation
atr = ta.atr(slAtrLen)
highestHigh = ta.highest(high, 7)
lowestLow = ta.lowest(low, 7)
longStop = showSLLines ? lowestLow - (atr * 1) : na
shortStop = showSLLines ? highestHigh + (atr * 1) : na
plot(longStop, title="Buy SL", color=color.green, style=plot.style_cross)
plot(shortStop, title="Sell SL", color=color.red, style=plot.style_cross)
// Momentum: rsi
rsi = ta.rsi(close, rsiLen)
// trend: EMA200
ema = ta.ema(close, trendPeriod)
plot(hideTrend ? na : ema, "EMA Trend", color=close > ema ? color.green : color.red, linewidth = 1)
// Volume-Weighed Moving Average calculation
vwmaAvg = ta.vwma(close, volAvg)
vwma_latest = volume
// plotshape((barstate.isconfirmed and (vwma_latest > (vwmaAvg * volThreshold))), title='VolumeData', text='', location=location.abovebar, style=shape.diamond, color=color.gray, textcolor=color.gray, size=size.tiny)
// Trade signals
longCond = barstate.isconfirmed and (ta.crossover(close, orb_high) or ta.crossover(close, dh)) and green(open, close) and (ignoreMementumVolume ? true : rsi > rsiBullish and (vwma_latest > (vwmaAvg * volThreshold)))
shortCond = barstate.isconfirmed and (ta.crossunder(close, orb_low) or ta.crossunder(close, dl)) and red(open, close) and (ignoreMementumVolume ? true : rsi < rsiBearish and (vwma_latest > (vwmaAvg * volThreshold)))
plotshape(longCond, title='Breakout', text='BO', location=location.belowbar, style=shape.triangleup, color=color.green, textcolor=color.green)
plotshape(shortCond, title='Breakout', text='BD', location=location.abovebar, style=shape.triangledown, color=color.red, textcolor=color.red)
// Trade execute
h = hour(time('1'), syminfo.timezone)
m = minute(time('1'), syminfo.timezone)
hourVal = h * 100 + m
totalTrades = strategy.opentrades + strategy.closedtrades
if (mktAlwaysOn or (hourVal < endOfDay))
// Entry
var float sl = na
var float target = na
if (longCond)
strategy.entry("enter long", strategy.long, lotSize, limit=na, stop=na, comment="Enter Long")
sl := longStop
target := close + ((close - longStop) * rrRatio)
alert('Buy:' + syminfo.ticker + ' ,SL:' + str.tostring(math.floor(sl)) + ', Target:' + str.tostring(target), alert.freq_once_per_bar)
if (shortCond)
strategy.entry("enter short", strategy.short, lotSize, limit=na, stop=na, comment="Enter Short")
sl := shortStop
target := close - ((shortStop - close) * rrRatio)
alert('Sell:' + syminfo.ticker + ' ,SL:' + str.tostring(math.floor(sl)) + ', Target:' + str.tostring(target), alert.freq_once_per_bar)
// Exit: target or SL
if ((close >= target) or (close <= sl))
strategy.close("enter long", comment=close < sl ? "Long SL hit" : "Long target hit")
if ((close <= target) or (close >= sl))
strategy.close("enter short", comment=close > sl ? "Short SL hit" : "Short target hit")
else if (not mktAlwaysOn)
// Close all open position at the end if Day
strategy.close_all(comment = "Close all entries at end of day.")
// Plotting table
if (not hideTable and is_end_session)
message = syminfo.ticker + " :\n\nORB Upper: " + str.tostring(math.round(orb_high)) + "\nORB Lower: " + str.tostring(math.round(orb_low)) + "\nPDH: " + str.tostring(math.round(dh)) + "\nPDC: " + str.tostring(math.round(dc)) + "\nPDL: " + str.tostring(math.round(dl)) + "\nVWAP: " + str.tostring(math.round(ta.vwap(close)))
printTable(message)
alert(message, alert.freq_once_per_bar_close)