
Artikel ini membincangkan strategi perdagangan algoritma yang menggunakan corak pengapukan untuk mengenal pasti peluang keuntungan dan harga yang bersilang dengan purata bergerak sebagai isyarat masuk. Strategi ini menggabungkan analisis teknikal harga dan kaedah pengesanan trend untuk mengumpul dan membalikkan trend.
Logik utama strategi ini adalah berdasarkan gabungan dua penunjuk yang tidak berkaitan:
Metoda menelan: satu model pembalikan dua garis K, di mana entiti pada garis K kedua benar-benar menelan entiti pada garis K pertama, untuk mengenal pasti peluang pembalikan.
Harga dan purata bergerak bersilang: apabila harga dari bawah purata bergerak menembusi ke atas rata-rata bergerak bersilang, menghasilkan isyarat membeli; apabila harga dari atas purata bergerak menembusi ke bawah rata-rata bergerak bersilang, menghasilkan isyarat menjual.
Menerima masa di mana pasaran mungkin berbalik dengan mengambil corak, dan kemudian menggabungkan harga dengan penembusan purata bergerak sebagai isyarat penapis untuk menentukan pembalikan, dapat meningkatkan kebarangkalian keuntungan.
Khususnya, strategi ini menilai kemungkinan penukaran dan pembalikan dengan mengesan tiga bentuk penyapu: penyapu berbilang, penyapu kosong dan penyapu tanpa bayangan. Kemudian, gabungan harga dengan penapis isyarat garpu emas dan garpu mati pada rata-rata bergerak, akhirnya memutuskan arah untuk membuka kedudukan.
Kelebihan terbesar strategi ini adalah menggunakan gabungan petunjuk yang tidak berkaitan untuk meningkatkan keputusan. Pemerolehan corak menilai masa dan kebarangkalian pembalikan pasaran; dan harga dan rata-rata bergerak yang disalibkan untuk mengesahkan arah dan kekuatan pembalikan. Kedua-duanya saling mengesahkan dan dapat mengurangkan kerugian perdagangan yang disebabkan oleh isyarat palsu.
Kelebihan lain ialah fleksibiliti dalam menetapkan parameter. Pengguna boleh menetapkan sendiri parameter seperti kitaran purata bergerak, stop loss, dan lain-lain untuk mengoptimumkan strategi.
Walaupun menggunakan pelbagai petunjuk untuk meningkatkan keputusan, strategi ini masih mempunyai risiko isyarat palsu tertentu. Bentuk penelan bukanlah isyarat pembalikan yang dipercayai seratus peratus, dan persilangan harga dengan purata bergerak juga akan gagal.
Selain itu, seperti kebanyakan strategi analisis teknikal, strategi ini juga kurang berkesan dalam keadaan konflik seperti pergerakan harga. Pertembungan berterusan boleh mencetuskan stop loss atau memendekkan ruang keuntungan.
Untuk mengawal risiko, parameter purata bergerak boleh disesuaikan dengan sewajarnya, mengoptimumkan stop loss. Anda juga boleh mempertimbangkan tahap penglibatan strategi penyesuaian dinamik, digabungkan dengan indikator lain untuk mengenal pasti trend dan keadaan gegaran.
Strategi ini boleh dioptimumkan dengan:
Uji lebih banyak jenis purata bergerak untuk mencari kombinasi parameter yang terbaik. Contohnya, purata bergerak berat, purata bergerak yang diselewengkan secara berturut-turut dan sebagainya.
Tambah indikator trend untuk mengelakkan pergerakan yang bergolak. Contohnya ADX, Bollinger Bands dan sebagainya.
Mengoptimumkan cara menghentikan kerugian, meningkatkan kesan menghentikan kerugian. Anda boleh mempertimbangkan strategi menghentikan kerugian seperti Tracking Stop, Chandelier Exit.
Menambah kaedah pembelajaran mesin untuk menilai bentuk K-line, meningkatkan ketepatan pengenalan pengapungan.
Tambah fungsi pengoptimuman parameter automatik untuk menyesuaikan parameter.
Strategi ini menilai masa berbalik dengan memakan bentuk, dan mengesahkan arah berbalik dengan harga dan purata bergerak. Meningkatkan keberkesanan keputusan melalui penggabungan penunjuk, merupakan strategi analisis teknikal. Kelebihan adalah penunjuk saling melengkapi, parameter fleksibel; Kelemahannya adalah masih ada risiko isyarat palsu, lemah terhadap keadaan getaran.
/*backtest
start: 2023-12-30 00:00:00
end: 2024-01-29 00:00:00
period: 3h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=4
//@author=Daveatt
StrategyName = "BEST Engulfing + MA"
ShortStrategyName = "BEST Engulfing + MA"
strategy(title=StrategyName, shorttitle=ShortStrategyName, overlay=true)
includeEngulfing = true
includeMA = true
source_ma = input(title="Source Price vs MA", type=input.source, defval=close)
typeofMA = input(title="Type of MA", defval="SMA", options=["RMA", "SMA", "EMA", "WMA", "VWMA", "SMMA", "KMA", "TMA", "HullMA", "DEMA", "TEMA"])
length_ma = input(32, title = "MA Length", type=input.integer)
// ---------- Candle components and states
GreenCandle = close > open
RedCandle = close < open
NoBody = close==open
Body = abs(close-open)
// bullish conditions
isBullishEngulfing1 = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and GreenCandle and RedCandle[1]
isBullishEngulfing2 = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) <= min(close,open) and Body > Body[1] and GreenCandle and RedCandle[1]
// bearish conditions
isBearishEngulfing1 = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and RedCandle and GreenCandle[1]
isBearishEngulfing2 = max(close[1],open[1]) >= max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and RedCandle and GreenCandle[1]
// consolidation of conditions
isBullishEngulfing = isBullishEngulfing1 or isBullishEngulfing2
isBearishEngulfing = isBearishEngulfing1 or isBearishEngulfing2
//isBullishEngulfing = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and GreenCandle and RedCandle[1]
//isBearishEngulfing = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and RedCandle and GreenCandle[1]
Engulf_curr = 0 - barssince(isBearishEngulfing) + barssince(isBullishEngulfing)
Engulf_Buy = Engulf_curr < 0 ? 1 : 0
Engulf_Sell = Engulf_curr > 0 ? 1 : 0
// Price vs MM
smma(src, len) =>
smma = 0.0
smma := na(smma[1]) ? sma(src, len) : (smma[1] * (len - 1) + src) / len
smma
ma(smoothing, src, length) =>
if smoothing == "RMA"
rma(src, length)
else
if smoothing == "SMA"
sma(src, length)
else
if smoothing == "EMA"
ema(src, length)
else
if smoothing == "WMA"
wma(src, length)
else
if smoothing == "VWMA"
vwma(src, length)
else
if smoothing == "SMMA"
smma(src, length)
else
if smoothing == "HullMA"
wma(2 * wma(src, length / 2) - wma(src, length), round(sqrt(length)))
else
if smoothing == "LSMA"
src
else
if smoothing == "KMA"
xPrice = src
xvnoise = abs(xPrice - xPrice[1])
nfastend = 0.666
nslowend = 0.0645
nsignal = abs(xPrice - xPrice[length])
nnoise = sum(xvnoise, length)
nefratio = iff(nnoise != 0, nsignal / nnoise, 0)
nsmooth = pow(nefratio * (nfastend - nslowend) + nslowend, 2)
nAMA = 0.0
nAMA := nz(nAMA[1]) + nsmooth * (xPrice - nz(nAMA[1]))
nAMA
else
if smoothing == "TMA"
sma(sma(close, length), length)
else
if smoothing == "DEMA"
2 * src - ema(src, length)
else
if smoothing == "TEMA"
3 * (src - ema(src, length)) + ema(ema(src, length), length)
else
src
MA = ma(typeofMA, source_ma, length_ma)
plot(MA, color=#006400FF, title="MA breakout", linewidth=3)
macrossover = crossover (source_ma, MA)
macrossunder = crossunder(source_ma, MA)
since_ma_buy = barssince(macrossover)
since_ma_sell = barssince(macrossunder)
macross_curr = 0 - since_ma_sell + since_ma_buy
bullish_MA_cond = macross_curr < 0 ? 1 : 0
bearish_MA_cond = macross_curr > 0 ? 1 : 0
posUp = (Engulf_Buy ? 1 : 0) + (bullish_MA_cond ? 1 : 0)
posDn = (Engulf_Sell ? 1 : 0) + (bearish_MA_cond ? 1 : 0)
conditionUP = posUp == 2 and posUp[1] < 2
conditionDN = posDn == 2 and posDn[1] < 2
sinceUP = barssince(conditionUP)
sinceDN = barssince(conditionDN)
// primary-first signal of the trend
nUP = crossunder(sinceUP,sinceDN)
nDN = crossover(sinceUP,sinceDN)
// and the following secondary signals
// save of the primary signal
sinceNUP = barssince(nUP)
sinceNDN = barssince(nDN)
buy_trend = sinceNDN > sinceNUP
sell_trend = sinceNDN < sinceNUP
// engulfing by
barcolor(nUP ? color.orange : na, title="Bullish condition")
barcolor(nDN ? color.yellow : na, title="Bearish condition")
isLong = nUP
isShort = nDN
long_entry_price = valuewhen(nUP, close, 0)
short_entry_price = valuewhen(nDN, close, 0)
longClose = close[1] < MA
shortClose = close[1] > MA
///////////////////////////////////////////////
//* Backtesting Period Selector | Component *//
///////////////////////////////////////////////
StartYear = input(2017, "Backtest Start Year",minval=1980)
StartMonth = input(1, "Backtest Start Month",minval=1,maxval=12)
StartDay = input(1, "Backtest Start Day",minval=1,maxval=31)
testPeriodStart = timestamp(StartYear,StartMonth,StartDay,0,0)
StopYear = input(2020, "Backtest Stop Year",minval=1980)
StopMonth = input(12, "Backtest Stop Month",minval=1,maxval=12)
StopDay = input(31, "Backtest Stop Day",minval=1,maxval=31)
testPeriodStop = timestamp(StopYear,StopMonth,StopDay,0,0)
testPeriod() => true
//////////////////////////
//* Profit Component *//
//////////////////////////
input_tp_pips = input(600, "Backtest Profit Goal (in USD)",minval=0)
input_sl_pips = input(300, "Backtest STOP Goal (in USD)",minval=0)
tp = buy_trend? long_entry_price + input_tp_pips : short_entry_price - input_tp_pips
sl = buy_trend? long_entry_price - input_sl_pips : short_entry_price + input_sl_pips
long_TP_exit = buy_trend and high >= tp
short_TP_exit = sell_trend and low <= tp
plot(tp, title="TP", style=plot.style_circles, linewidth=3, color=color.blue)
plot(sl, title="SL", style=plot.style_circles, linewidth=3, color=color.red)
if testPeriod()
strategy.entry("Long", 1, when=isLong)
strategy.close("Long", when=longClose )
strategy.exit("XL","Long", limit=tp, when=buy_trend, stop=sl)
if testPeriod()
strategy.entry("Short", 0, when=isShort)
strategy.close("Short", when=shortClose )
strategy.exit("XS","Short", when=sell_trend, limit=tp, stop=sl)