Strategi Mengikuti Trend Berdasarkan Penembusan Purata Bergerak

Penulis:ChaoZhang, Tarikh: 2023-10-30 12:22:28
Tag:

img

Ringkasan

Idea utama strategi ini adalah untuk mengikuti trend dengan mengesan pecah purata bergerak merentasi bingkai masa yang lebih tinggi. Apabila harga pecah di atas atau pecah di bawah purata bergerak pada bingkai masa yang lebih tinggi, ia menandakan kemungkinan permulaan trend baru, yang membolehkan peniaga mengambil kedudukan dengan sewajarnya.

Logika Strategi

Strategi ini dibangunkan dalam Pine Script dan terdiri daripada komponen utama berikut:

  1. Input

    Menentukan tempoh parameter input sebagai tempoh purata bergerak, lalai kepada 200; dan jangka masa sebagai jangka masa bar, lalai kepada D (bar harian).

  2. Purata Bergerak

    Mengira purata bergerak eksponensial (EMA) menggunakan fungsi ta.ema.

  3. Pengesanan Penembusan

    Mengenali gangguan dan gangguan menggunakan fungsi ta.crossover dan ta.crossunder.

  4. Merancang Isyarat

    Merancang anak panah ke atas dan ke bawah pada bar apabila pelarian berlaku.

  5. Masuk dan Keluar Dagangan

    Memasuki perdagangan pada isyarat pecah dan keluar apabila harga mencapai jarak stop loss 2x.

Strategi ini terutamanya memanfaatkan keupayaan trend berikut purata bergerak dalam jangka masa yang lebih tinggi.

Analisis Kelebihan

Kelebihan utama strategi ini termasuk:

  1. Logik yang mudah difahami dan dikuasai.

  2. Bergantung pada satu penunjuk sahaja, dengan penyesuaian parameter yang minimum.

  3. Isyarat pecah cenderung sejajar dengan trend, mengelakkan perdagangan berlebihan.

  4. Jangka masa yang lebih tinggi dengan jelas menggambarkan trend utama tanpa bunyi bising.

  5. Gabungan jangka masa yang fleksibel memenuhi keperluan produk yang berbeza.

  6. Mudah diskalakan di seluruh produk, mengelakkan pengeluaran serentak.

Analisis Risiko

Risiko yang berpotensi ialah:

  1. Isyarat pecah mungkin menjadi isyarat palsu, tidak dapat menapis bunyi bising pasaran dengan berkesan.

  2. Tidak dapat memanfaatkan peluang jangka pendek.

  3. Kerugian besar jika arah trend utama adalah salah.

  4. Ketidaksesuaian jangka masa antara purata bergerak dan jangka masa dagangan boleh menyebabkan perdagangan berlebihan atau kehilangan keuntungan.

  5. Kekurangan stop loss masa nyata boleh mengakibatkan kerugian yang diperbesar.

Penyelesaian yang mungkin termasuk menggabungkan dengan penunjuk trend, menambah penapis, memendekkan tempoh penahan, melaksanakan stop loss dinamik dan lain-lain.

Peluang Peningkatan

Strategi ini boleh ditingkatkan dalam aspek berikut:

  1. Tambah penunjuk trend seperti MACD, KD untuk meningkatkan kebolehpercayaan penembusan.

  2. Tambah penapis berdasarkan jumlah atau Bollinger Bands untuk mengelakkan pecah palsu.

  3. Mengoptimumkan penyesuaian parameter untuk memadankan tempoh penahan dengan kitaran trend.

  4. Menggabungkan stop loss masa nyata untuk mengawal kerugian perdagangan tunggal.

  5. meneroka teknik pembelajaran mesin untuk pengoptimuman parameter dinamik.

  6. Uji pelbagai gabungan peruntukan aset untuk meningkatkan kestabilan keseluruhan.

Kesimpulan

Ringkasnya, ini adalah strategi yang mudah dan praktikal untuk mengikuti trend melalui penembusan purata bergerak. Ia mudah difahami dan dilaksanakan, berfungsi sebagai strategi pengenalan yang baik untuk perdagangan algo. Tetapi ia juga mempunyai beberapa kelemahan yang perlu ditangani melalui kombinasi penunjuk, penyesuaian parameter, kehilangan berhenti dinamik dan lain-lain. Masih banyak ruang untuk penambahbaikan dan sambungan.


/*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)



Lebih lanjut