Cette stratégie combine les signaux potentiels d'inversion de tendance de l'indicateur Supertrend et de l'indicateur MACD, ainsi que les signaux de surachat/survente de l'indicateur RSI, pour former un système relativement stable et efficace de signaux d'entrée et de sortie.
La logique de base de cette stratégie réside dans l'utilisation combinée de l'indicateur Supertrend et de l'indicateur MACD comme critères pour les signaux d'entrée.
Sur la partie Supertrend, la stratégie adopte le changement de direction de l'indicateur Supertrend comme signal d'inversion potentiel.
Sur la partie MACD, la stratégie utilise la pente et le croisement de la ligne zéro de l'indicateur MACD sur un laps de temps inférieur (quotidien) pour identifier les opportunités d'inversion potentielles. Lorsque la valeur absolue de la pente MACD est grande (au-dessus du seuil) et que la pente maintient une tendance à la hausse, un signal est généré. Si la ligne MACD traverse la ligne zéro, un signal auxiliaire est généré.
Pour les signaux d'entrée, la stratégie exige que le signal Supertrend et le signal MACD soient dans la même direction avant d'envoyer des ordres de négociation.
En outre, pour les signaux de sortie, la stratégie adopte également les signaux de surachat / survente de l'indicateur RSI. Lorsque le RSI dépasse 80, un signal de vente est généré. Lorsque le RSI tombe en dessous de 20, un signal d'achat est généré. Ceux-ci aident à déterminer le moment de l'inversion.
L'avantage majeur de cette stratégie est la diversité des signaux d'indicateur, qui peuvent se compléter et rendre le signal global plus stable et fiable.
Les signaux d'inversion de super-tendance peuvent capturer des tendances à court terme relativement fortes; la pente MACD peut juger de la force de la tendance à moyen et long terme pour éviter d'être induit en erreur par de faux retours; le RSI peut fournir le meilleur moment d'entrée et de sortie sur le marché en indiquant des niveaux de surachat / survente.
En outre, la conception du calendrier est également raisonnable. Supertrend utilise le calendrier horaire tandis que le MACD utilise le calendrier quotidien. Cela garantit à la fois la fréquence des transactions et la stabilité du jugement des tendances.
Le principal risque de cette stratégie est la forte probabilité de confusion des signaux entre différents indicateurs. Par exemple, Supertrend peut donner un faux renversement alors que le signal MACD ne se synchronise pas. Cela pourrait entraîner des pertes inutiles.
En outre, l'indice de volatilité pour déterminer le moment de la sortie peut également être trop tôt ou trop tard, ce qui empêche la durée maximale de détention.
Enfin, un seuil de pente MACD surdimensionné peut également manquer des opportunités d'inversion plus faibles.
Cette stratégie peut être encore optimisée par les aspects suivants:
Mettre en place un mécanisme de stop-loss lorsque la perte dépasse un certain pourcentage.
Ajouter un seuil dynamique pour le jugement de la pente du MACD. Augmenter le seuil de pente lorsque la volatilité du marché est élevée et abaisser le seuil lorsque le marché est stable.
Ajouter la condition de rebond pour le jugement de sortie du RSI. Exiger un rappel significatif après que le RSI a dépassé 80 avant d'envisager de fermer la position.
Tester le MACD avec le volume et voir s'il améliore la fiabilité du signal
Essayez de régler automatiquement les paramètres pour trouver les paramètres optimaux
La
/*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)