Diese Strategie kombiniert die potenziellen Trendumkehrsignale des Supertrend-Indikators und des MACD-Indikators mit den Überkauf-/Überverkaufssignalen des RSI-Indikators, um ein relativ stabiles und effizientes System für Ein- und Ausstiegssignale zu bilden.
Die Kernlogik dieser Strategie liegt in der Kombination von Supertrend-Indikator und MACD-Indikator als Kriterien für Einstiegssignale.
Der Supertrend-Teil der Strategie verwendet die Richtungsänderung des Supertrend-Indikators als potenzielles Umkehrsignal. Wenn sich die Supertrend-Richtung von oben nach unten dreht, wird ein Kaufsignal generiert. Wenn sich die Richtung von unten nach oben dreht, wird ein Verkaufssignal generiert.
Auf dem MACD-Teil verwendet die Strategie die Neigung und Nulllinie Crossover des MACD-Indikators auf niedrigeren Zeitrahmen (täglich), um potenzielle Umkehrmöglichkeiten zu identifizieren. Wenn der absolute Wert der MACD-Neigung groß ist (über der Schwelle) und die Neigung den Aufwärtstrend beibehält, wird ein Signal generiert. Wenn die MACD-Linie die Nulllinie überschreitet, wird ein Hilfssignal generiert. MACD-Signale sind in der Regel glatter als Supertrend-Signale.
Für Einstiegssignale erfordert die Strategie, dass sich das Supertrend-Signal und das MACD-Signal vor dem Senden von Handelsaufträgen in die gleiche Richtung bewegen.
Darüber hinaus wird für Exit-Signale die Strategie auch die Überkauf/Überverkauf-Signale aus dem RSI-Indikator übernimmt. Wenn der RSI über 80 geht, wird ein Verkaufssignal generiert. Wenn der RSI unter 20 fällt, wird ein Kaufsignal generiert. Diese helfen, den Umkehrzeitpunkt zu bestimmen.
Der größte Vorteil dieser Strategie ist die Vielfalt der Indikatorsignale, die sich ergänzen und das Gesamtsignal stabiler und zuverlässiger machen.
Supertrend-Umkehrsignale können relativ starke kurzfristige Trends erfassen; die MACD-Spannung kann die mittelfristige Trendstärke beurteilen, um nicht durch falsche Umkehrungen irregeführt zu werden; der RSI kann den besten Ein- und Ausstiegszeitpunkt in einem Bereichsmarkt bieten, indem er überkaufte/überverkaufte Niveaus anzeigt.
Darüber hinaus ist auch das Zeitrahmendesign vernünftig. Supertrend verwendet stündliche Zeitrahmen, während MACD tägliche Zeitrahmen verwendet. Dies gewährleistet sowohl Handelsfrequenz als auch Stabilität beim Trendbeurteilungsverfahren.
Das Hauptrisiko dieser Strategie ist die hohe Wahrscheinlichkeit, dass Signale zwischen verschiedenen Indikatoren verwechselt werden. Zum Beispiel kann Supertrend eine falsche Umkehrung geben, während das MACD-Signal nicht synchronisiert. Dies könnte zu unnötigen Verlusten führen.
Darüber hinaus kann der RSI zur Bestimmung des Ausgangszeitraums auch zu früh oder zu spät sein, was die maximale Haltedauer verhindert.
Schließlich kann eine übergroße MACD-Neigungsschwelle auch schwächere Umkehrmöglichkeiten verpassen.
Diese Strategie kann aus folgenden Gesichtspunkten weiter optimiert werden:
Einführen Sie einen Stop-Loss-Mechanismus, wenn der Verlust einen bestimmten Prozentsatz übersteigt.
Hinzufügen einer dynamischen Schwelle für die MACD-Spannungsbeurteilung; Anhebung der Schwelle, wenn die Marktvolatilität hoch ist, und Senkung der Schwelle, wenn der Markt stabil ist.
Hinzufügen einer Rücknahmebedingung für das RSI-Ausgangsgericht.
Test MACD mit Volumen und sehen, ob es die Signalzuverlässigkeit verbessert
Versuchen Sie automatisches Parameter-Tuning, um optimale Einstellungen zu finden
Die
/*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)