Strategi ini menggabungkan isyarat pembalikan trend yang berpotensi dari penunjuk Supertrend dan penunjuk MACD, bersama dengan isyarat overbought / oversold dari penunjuk RSI, untuk membentuk sistem yang agak stabil dan cekap untuk isyarat masuk dan keluar.
Logik teras strategi ini terletak pada penggunaan gabungan penunjuk Supertrend dan penunjuk MACD sebagai kriteria untuk isyarat kemasukan.
Pada bahagian Supertrend, strategi ini menggunakan perubahan arah penunjuk Supertrend sebagai isyarat pembalikan yang berpotensi. Apabila arah Supertrend berputar dari atas ke bawah, isyarat beli dihasilkan. Apabila arah berputar dari bawah ke atas, isyarat jual dihasilkan.
Pada bahagian MACD, strategi ini menggunakan kemiringan dan persilangan garis sifar penunjuk MACD pada jangka masa yang lebih rendah (tiap hari) untuk mengenal pasti peluang pembalikan yang berpotensi. Apabila nilai mutlak kemiringan MACD besar (di atas ambang) dan kemiringan mengekalkan trend menaik, isyarat dihasilkan. Jika garis MACD melintasi garis sifar, isyarat tambahan dihasilkan. Isyarat MACD biasanya lebih lancar daripada yang Supertrend.
Untuk isyarat masuk, strategi memerlukan isyarat Supertrend dan isyarat MACD berada dalam arah yang sama sebelum menghantar pesanan dagangan.
Di samping itu, untuk isyarat keluar, strategi ini juga menggunakan isyarat overbought / oversold dari penunjuk RSI. Apabila RSI melebihi 80, isyarat jual dihasilkan. Apabila RSI turun di bawah 20, isyarat beli dihasilkan. Ini membantu menentukan masa pembalikan.
Kelebihan terbesar strategi ini adalah kepelbagaian isyarat penunjuk.
Isyarat pembalikan supertrend boleh menangkap trend jangka pendek yang agak kuat; kemiringan MACD dapat menilai kekuatan trend jangka menengah dan panjang untuk mengelakkan tertipu oleh pembalikan palsu; RSI boleh memberikan masa masuk dan keluar terbaik di pasaran terhad dengan menunjukkan tahap overbought / oversold. Menumpuk isyarat dari beberapa penunjuk boleh menapis beberapa perdagangan bising dan mencapai kadar kemenangan yang lebih tinggi.
Selain itu, reka bentuk jangka masa juga munasabah. Supertrend menggunakan jangka masa sejam manakala MACD menggunakan jangka masa harian. Ini memastikan kekerapan perdagangan dan kestabilan dalam penilaian trend.
Risiko utama strategi ini adalah kebarangkalian tinggi untuk mengelirukan isyarat antara penunjuk yang berbeza. Sebagai contoh, Supertrend boleh memberikan pembalikan palsu sementara isyarat MACD tidak menyelaras. Ini boleh menyebabkan kerugian yang tidak perlu.
Di samping itu, RSI untuk menentukan masa keluar juga boleh terlalu awal atau terlalu lewat, menghalang tempoh pegangan maksimum.
Akhirnya, ambang kemiringan MACD yang terlalu besar juga mungkin terlepas peluang pembalikan yang lebih lemah.
Strategi ini boleh dioptimumkan lagi dari aspek berikut:
Memperkenalkan mekanisme stop loss. Stop loss apabila kerugian melebihi peratusan tertentu.
Tambah ambang dinamik untuk penghakiman kemiringan MACD. Tingkatkan ambang kemiringan apabila turun naik pasaran tinggi, dan ambang yang lebih rendah apabila pasaran stabil.
Tambah syarat pulback untuk penilaian keluar RSI. Minta panggilan balik yang signifikan selepas RSI melebihi 80 sebelum mempertimbangkan kedudukan penutupan.
Uji MACD dengan jumlah dan lihat sama ada ia meningkatkan kebolehpercayaan isyarat
Mencuba penyesuaian parameter automatik untuk mencari tetapan optimum
/*backtest start: 2022-12-19 00:00:00 end: 2023-12-25 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 strategy("SuperTrend.MACD Strategy", overlay=false, default_qty_type=strategy.percent_of_equity, default_qty_value=100, initial_capital=100000, pyramiding=5, process_orders_on_close=true) // ---------------- Utility Functions ---------------- getArrayValue(float[] arr, int ago) => if ago >= 0 array.get(arr, ago >= array.size(arr) ? na: array.size(arr) + -1 * ago -1) else na filterNA(float[] a, s, int y) => int x = 0 if not na(s[0]) array.push(a, s[0]) if array.size(a) > y array.shift(a) a pine_rsi(float[] x, int y) => x0 = getArrayValue(x, 0) x1 = getArrayValue(x, 1) u = math.max(x0 - x1, 0) // upward ta.change d = math.max(x1 - x0, 0) // downward ta.change rs = ta.rma(u, y) / ta.rma(d, y) res = 100 - 100 / (1 + rs) res turnAround(float[] arr) => int isTurnAround = 0 now = getArrayValue(arr, 0) p1 = getArrayValue(arr, 1) p2 = getArrayValue(arr, 2) if p1 > now and p1 > p2 isTurnAround := -1 else if p1 < now and p1 < p2 isTurnAround := 1 intergerizeSignal(i) => i>0 ? 1 : i<0 ? -1 : 0 linreg(float[] y, int n, int offset=0) => float slope = na float intercept = na int endcursor = offset + n - 1 if array.size(y) > endcursor float sumX = 0 float sumX2 = 0 float sumY = 0 float sumY2 = 0 float sumXY = 0 for i=offset to endcursor yv = array.get(y, i) sumY += yv sumY2 += math.pow(yv, 2) sumX += i sumX2 += math.pow(i, 2) sumXY += i*yv // Pearson correlation coefficient r = (n * sumXY - sumX * sumY) / math.sqrt((n * sumY2 - math.pow(sumY, 2)) * (n * sumX2 - math.pow(sumX, 2))) // Coefficient of determination r2 = math.pow(r, 2) meanX = sumX / n meanY = sumY / n slope := (n * sumXY - sumX * sumY) / (n * sumX2 - math.pow(sumX, 2)) intercept := meanY - slope * meanX [slope, intercept] isStartOfDay() => dayofweek != dayofweek[1] // ---------------- Variables ---------------- varip float st_signal = 0 varip float macd_signal = 0 varip float macd_close_signal = 0 varip float histo_signal = 0 var int openSignal = 0 var int closeSignal = 0 // -------------------------------- Supertrend Signal (Open) -------------------------------- // ST calculation atrPeriod = input(10, "Supertrend ATR Length") factor = input.float(2.0, "Supertrend Factor", step = 0.01) [_, direction] = ta.supertrend(factor, atrPeriod) st_direction_change = ta.change(direction) if st_direction_change < 0 st_signal := 4 if st_direction_change > 0 st_signal := -4 // -------------------------------- MACD Signal (Open + Close) -------------------------------- // MACD Calculation fastLength = input(12, title="MACD Fast Length") slowLength = input(26, title="MACD Slow Length") signalLength = input(9, title="MACD Signal Length") macdSlowTimeframe = input.timeframe("D", "MACD Timeframe") macdSlopeLookbackOpen = input(7, title="MACD Slope Lookback - Open") macdSlopeLookbackClose = input(3, title="MACD Slope Lookback - Close") dailyClose = request.security(syminfo.tickerid, macdSlowTimeframe, close, barmerge.gaps_on) [macdLine, signalLine, _] = ta.macd(dailyClose, fastLength, slowLength, signalLength) // MACD Slope calculation varip macdHistory = array.new<float>(0) varip macdSlowSlopeArr = array.new<float>(0) varip float macdSlowSlope = na varip float macdCloseSlope = na if not na(macdLine[0]) array.push(macdHistory, macdLine[0]) if array.size(macdHistory) > macdSlopeLookbackOpen array.shift(macdHistory) [s1, _] = linreg(macdHistory, macdSlopeLookbackOpen) macdSlowSlope := s1 array.push(macdSlowSlopeArr, macdSlowSlope) if array.size(macdSlowSlopeArr) > macdSlopeLookbackClose array.shift(macdSlowSlopeArr) [s2, _] = linreg(macdSlowSlopeArr, macdSlopeLookbackClose) macdCloseSlope := s2 // MACD Signal Calculation // > open signal threshold_macdSlowSlope = input.float(0.75, "MACD Slope Open Threshold", step = 0.05) macdSlowSlopeOverThreshold = math.abs(macdSlowSlope) >= threshold_macdSlowSlope macdSlowSlopeTrend = macdSlowSlope - getArrayValue(macdSlowSlopeArr, 1) macdSlowSlopeTrendConfirm = macdSlowSlope*macdSlowSlopeTrend >0 if (macdSlowSlopeOverThreshold and macdSlowSlopeTrendConfirm) macd_signal := 3*macdSlowSlope/math.abs(macdSlowSlope) else macd_signal := 0 // > close signal int macdCloseSignal = 0 macdCloseSignal := intergerizeSignal(macdCloseSlope) // Histogram signal Calculation histSlow = macdLine - signalLine if (ta.crossover(histSlow, 0)) histo_signal := 2 if (ta.crossunder(histSlow, 0)) histo_signal := -2 // -------------------------------- RSI Signal (Close) -------------------------------- int rsiCloseSignal = 0 varip float rsiSlow = na rsiPeriod = input(14, title="RSI Period") varip dailyCloseRSIFilter = array.new_float() // rewrite pine_rsi to remove NaN value from series at calculation dailyCloseRSIFilter := filterNA(dailyCloseRSIFilter, dailyClose, rsiPeriod) if not na(dailyClose[0]) rsiSlow := pine_rsi(dailyCloseRSIFilter, rsiPeriod) if rsiSlow > 80 rsiCloseSignal := -1 else if rsiSlow < 20 rsiCloseSignal := 1 else rsiCloseSignal := 0 // -------------------------------- Overall Signal -------------------------------- // Close signal closeSignals = array.from(macdCloseSignal, rsiCloseSignal) closeSignal := array.includes(closeSignals, 1) ? 1 : array.includes(closeSignals, -1) ? -1 : 0 closeSignal := closeSignal * 5 // Open signal if (macd_signal * st_signal > 0) and (macd_signal * macd_close_signal >= 0) openSignal := intergerizeSignal(st_signal) openSignal := openSignal * 6 else openSignal := 0 // -------------------------------- Order -------------------------------- // if strategy.position_size == 0 if openSignal * closeSignal >=0 if openSignal > 0 strategy.entry("Long Entry", strategy.long) else if openSignal < 0 strategy.entry("Short Entry", strategy.short) if strategy.position_size != 0 if closeSignal < 0 strategy.close("Long Entry") if closeSignal > 0 strategy.close("Short Entry") // -------------------------------- Plot -------------------------------- plot(closeSignal, title="Close Signal", color=color.red, linewidth = 1, style=plot.style_area) plot(openSignal, title="Open Signal", color=color.green, linewidth = 1, style=plot.style_area) plot(st_signal, title="ST Signal", color=color.black, linewidth = 1, style=plot.style_circles) plot(macd_signal, title="MACD Signal", color=color.blue, linewidth = 1, style=plot.style_circles) // plot(macdSlowSlope, title="macd slow slope", color=color.purple, linewidth = 1, style=plot.style_line) // plot(macdCloseSlope, title="macd slow slope", color=color.lime, linewidth = 1, style=plot.style_line) hline(0, "Zero Line", color=color.gray)