Supertrend-MACD-Quantitative Strategie

Schriftsteller:ChaoZhang, Datum: 2023-12-26 11:13:24
Tags:

img

Übersicht

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.

Strategie Logik

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.

Analyse der Vorteile

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.

Risikoanalyse

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.

Optimierungsrichtlinien

Diese Strategie kann aus folgenden Gesichtspunkten weiter optimiert werden:

  1. Einführen Sie einen Stop-Loss-Mechanismus, wenn der Verlust einen bestimmten Prozentsatz übersteigt.

  2. 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.

  3. Hinzufügen einer Rücknahmebedingung für das RSI-Ausgangsgericht.

  4. Test MACD mit Volumen und sehen, ob es die Signalzuverlässigkeit verbessert

  5. Versuchen Sie automatisches Parameter-Tuning, um optimale Einstellungen zu finden

Schlussfolgerung

Die Supertrend MACD Quantitative Strategy kombiniert Signale aus mehreren Indikatoren, um Ein- und Ausstiegssignale zu liefern. Ihre Vorteile liegen in stabilen Signalen und relativ hoher Gewinnrate. Weitere Verbesserungen können durch Parameteroptimierung erzielt werden. Die Risiken und Optimierungsrichtungen konzentrieren sich hauptsächlich auf Parameterüberfitting-Probleme.


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


Mehr