Mehrfaktorstrategie

Schriftsteller:ChaoZhang, Datum: 31.10.2023
Tags:

img

Übersicht

Die Multi-Faktor-Strategie integriert Schwingungs-, Trend- und Breakout-Strategien in eine durch die Kombination ihrer Stärken.

Strategie Logik

Die Multifaktorstrategie basiert hauptsächlich auf folgenden Aspekten:

  • Der Schwingungsteil verwendet den Stochastik-Oszillator, um Kauf- und Verkaufssignale zu identifizieren. Insbesondere wird ein Kaufsignal erzeugt, wenn die %K-Linie über die %D-Linie aus der Überverkaufszone geht. Ein Verkaufssignal wird erzeugt, wenn die %K-Linie unter die %D-Linie aus der Überkaufszone geht.

  • Der Trend-Folgende Teil verwendet das goldene Kreuz der SMAs, um die Trendrichtung zu bestimmen. Ein Kaufsignal wird erzeugt, wenn der schnelle SMA über den langsamen SMA überschreitet. Ein Verkaufssignal wird erzeugt, wenn der schnelle SMA unter den langsamen SMA überschreitet.

  • Der Breakout-Teil überwacht, ob der Preis in einem bestimmten Zeitraum über den höchsten Preis oder unter den niedrigsten Preis bricht.

  • Der ADX-Indikator wird verwendet, um die Trendstärke zu messen.

  • Um die Rentabilität zu optimieren, werden Stop-Loss- und Take-Profit-Linien eingeführt.

Zusammenfassend folgt die Mehrfaktorstrategie folgender Logik:

  1. Wenn der ADX über einer Schwelle liegt, gilt der Trend als stark. Die Trendstrategie wirkt. Wenn der ADX unter der Schwelle liegt, ist der Markt im Bereich. Nur die oszillierende Strategie wirkt.

  2. In einem Trendmarkt löst das goldene Kreuz des SMA einen Long-Eintrag aus und das Death-Cross löst einen Exit aus.

  3. In einem Rangiermarkt werden Handelssignale des Stochastic-Oszillators befolgt.

  4. Die Breakout-Strategie gilt bei beiden Marktbedingungen, um einer starken Dynamik zu folgen.

  5. Die Stop-Loss- und Take-Profit-Linien werden eingestellt, um Gewinne zu erzielen und Verluste zu begrenzen.

Analyse der Vorteile

Der größte Vorteil der Multifaktorstrategie besteht darin, dass sie die Stärken verschiedener Strategien kombiniert und eine gute Performance sowohl auf Trend- als auch auf Schwellenmärkten erzielt.

  1. Es reitet gut auf Trends und erzielt hohe Gewinnraten in Trendmärkten.

  2. Sie kann von den Märkten mit begrenztem Marktumfang profitieren und vermeidet, in Positionen stecken zu bleiben.

  3. Es verfügt über hohe Gewinnfaktoren mit ordnungsgemäß eingestellten Stop Loss und Take Profit.

  4. Es wird die Trendstärke berücksichtigt, um Verluste durch falsche Signale zu reduzieren.

  5. Die Kombination mehrerer Indikatoren führt zu starken Handelssignalen.

  6. Die Parameter können für eine bessere Leistung optimiert werden.

Risikoanalyse

Es bestehen auch Risiken im Zusammenhang mit der Mehrfaktorstrategie:

  1. Eine falsche Kombination von Faktoren kann zu widersprüchlichen Handelssignalen führen.

  2. Mehrere Parameter erhöhen die Schwierigkeit der Optimierung und erfordern ausreichende historische Daten.

  3. Es kann vorkommen, dass es bei einer Umkehr des Trends nicht in der Zeit gelingt, Positionen zu verlassen, was zu großen Verlusten führt.

  4. Der ADX-Indikator hat Verzögerungseffekte und kann Trendwendepunkte verpassen.

  5. Der Breakout-Handel ist anfällig für Verlustpositionen. Ein angemessener Stop-Loss ist erforderlich.

Die Risiken können durch folgende Maßnahmen gemildert werden:

  1. Die Stabilität der Faktoren überprüfen und stabile auswählen.

  2. Verwenden von heuristischen Optimierungsalgorithmen, um die optimalen Parameter zu finden.

  3. Richtige Stop-Loss-Einstellungen zur Kontrolle des maximalen Drawdowns.

  4. Einbeziehung zusätzlicher Indikatoren zur Erkennung einer Trendwende.

  5. Optimierung der Stop-Loss-Regeln für den Breakout-Handel.

Verbesserungsrichtlinien

Es gibt noch viel zu tun, um die Multifaktorstrategie zu verbessern:

  1. Mehr Faktoren wie Volatilität, Volumen usw. testen, um bessere Kombinationen zu finden.

  2. Mit Hilfe von Maschinellen Lerntechniken, um die Faktorgewichte dynamisch zu optimieren.

  3. Nutzung heuristischer Algorithmen für eine schnelle Parameteroptimierung.

  4. Erprobung der Rentabilität in verschiedenen Haltungszeiten.

  5. Erforschung dynamischer Stop-Loss-Regeln, z. B. Erweiterung des Stop-Loss nach Gewinn.

  6. Mehr Filter wie Lautstärken hinzufügen, um die Signalqualität zu verbessern.

  7. Optimierung der ADX-Parameter oder Verwendung fortschrittlicherer Trenddetektionsindikatoren.

Schlussfolgerung

Die Multi-Faktor-Strategie kombiniert mehrere Handelslogiken wie Trend, Mean-Reversion und Breakout. Sie erzielt gute Performance sowohl auf Trending- als auch auf Ranging-Märkten. Im Vergleich zu Single-Faktor-Strategien bietet sie eine stabilere Rendite und hat ein großes Potenzial für Upgrades. Allerdings kann die Parameteroptimierung schwierig sein und erfordert ausreichende historische Daten. Insgesamt ist die Multi-Faktor-Strategie eine sehr effektive algorithmische Handelstechnik, die weitere Forschung und Optimierung wert ist.


/*backtest
start: 2023-09-30 00:00:00
end: 2023-10-30 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4

// strategy("Strategy_1", shorttitle="Strategy1",overlay=true ,pyramiding = 12, initial_capital=25000, currency='EUR', commission_type = strategy.commission.cash_per_order, commission_value = 3, default_qty_type = strategy.percent_of_equity, default_qty_value = 20)
	
// Revision:        1
// Author:          Jonas

// === INPUT ===
    //   > BACKTEST RANGE <
FromMonth = input(defval=1, title="From Month", minval=1, maxval=12)
FromDay = input(defval=1, title="From Day", minval=1, maxval=31)
FromYear = input(defval=2017, title="From Year", minval=2010)
ToMonth = input(defval=1, title="To Month", minval=1, maxval=12)
ToDay = input(defval=1, title="To Day", minval=1, maxval=31)
ToYear = input(defval=9999, title="To Year", minval=2010)

    //   > STRATEGY SETTINGS <
bolOS = input(defval = false, type=input.bool, title="Oscillating Strategy")
bolTS = input(defval = true, type=input.bool, title="Trend Strategy")
bolBO = input(defval = false, type=input.bool, title="Breakout Strategy")

strStrategy = input(defval = "Long", type=input.string, title="Trade Strategy",options = ["Long", "Short","Long & Short"])

flStopLoss = input(defval = 2.0, title="Stop Loss %", type=input.float)/100
flTakeProfit = input(defval = 4.0, title="Take Profit %", type=input.float)/100

    //   > SMA <

fastMA = input(defval=8, type=input.integer, title="FastMA length", minval=1, step=1)
slowMA = input(defval=21, type=input.integer, title="SlowMA length", minval=1, step=1)

    //  > ADX <
adx_len = input(defval=10, type=input.integer, title="ADX length", minval=1, step=1)
adx_trend = input(defval=30, type=input.integer, title="ADX Tr", minval=1, step=1)
adx_choppy = adx_trend
adx_limit = adx_trend

    //  > TRENDSCORE <
ts_fromIndex = input(title="From", type=input.integer, minval=1, defval=10)
ts_toIndex = input(title="To", type=input.integer, minval=1, defval=14)
ts_src = input(title="Source", type=input.source, defval=close)

    // > Oscillator <
stoch_length = 14
stoch_OverBought = 75
stoch_OverSold = 25
stoch_smoothK = 3
stoch_smoothD = 3

// === BACK TEST RANGE FUNCTION ===
window_start = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
window_finish = timestamp(ToYear, ToMonth, ToDay, 23, 59)  // backtest finish window
window() =>  // create function "within window of time"
    time >= window_start and time <= window_finish ? true : false

//plot(stop_level_Long, title="TEST",color=color.red, style=plot.style_linebr, linewidth=2)
//plot(take_level_Long, color=color.green, style=plot.style_linebr, linewidth=2)

// === ADX ===
adx_up = change(high)
adx_down = -change(low)
adx_trur = rma(tr, adx_len)
adx_plus = fixnan(100 * rma(adx_up > adx_down and adx_up > 0 ? adx_up : 0, adx_len) / adx_trur)
adx_minus = fixnan(100 * rma(adx_down > adx_up and adx_down > 0 ? adx_down : 0, adx_len) / adx_trur)
adx_sum = adx_plus + adx_minus

ADX = 100 * rma(abs(adx_plus - adx_minus) / (adx_sum == 0 ? 1 : adx_sum), adx_len)

//=== TRENDSCORE ===
trendscore(ts_src, ts_fromIndex, ts_toIndex) =>
	ts_sum = 0.0
	for i = ts_fromIndex to ts_toIndex
        ts_sum := ts_sum + (ts_src >= nz(ts_src[i]) ? 1 : -1)
    ts_sum

intTS = trendscore(ts_src, ts_fromIndex, ts_toIndex)
// Long if  TrendDirection = 1, Short if TrendDirection = -1; Indifferent if TrendDirection = 0
intTrendDirection = (intTS > (ts_toIndex-ts_fromIndex)) ? 1 : (intTS < (ts_fromIndex-ts_toIndex)) ? -1 : 0

    //  > TREND CONDITION <
adx_growing = ADX > highest(ADX[1],3)
intTrend = ((ADX >= adx_limit) and (ADX[1] >= adx_limit) and adx_growing) ? intTrendDirection : 0

// === ATR ===
ATR = sma(tr,10)
ATR_100 = ATR /abs(high - low)


// === STOCHASTICS ===

stoch_k = sma(stoch(close, high, low, stoch_length), stoch_smoothK)
stoch_d = sma(stoch_k, stoch_smoothD)

// === FILTER & CONDITIONS ===
    //  > STOCHASTICS <
bolFilter_OS1 = close[1] > hl2[1]



bolSigOsc_long_1 = (na(stoch_k) or na(stoch_d)) ? false : (crossover(stoch_d,stoch_OverSold) and stoch_k > stoch_d) ? true:false
bolSigOsc_short_1 = (na(stoch_k) or na(stoch_d)) ? false : (crossunder(stoch_d,stoch_OverBought) and stoch_k < stoch_d) ? true:false

bolLongOpenOS = bolSigOsc_long_1 and bolFilter_OS1
bolLongCloseOS = bolSigOsc_short_1

bolShortOpenOS = bolSigOsc_short_1 and bolFilter_OS1
bolShortCloseOS = bolSigOsc_long_1

    //  > TREND <

bolFilter_TS1 = close[1] > hl2[1] and open[1] < hl2[1]
bolFilter_TS2 = sma(close,50)>sma(close,50)[10]
bolFilter_TS3 = close[1] < hl2[1] and open[1] > hl2[1]

bolSigTrendLO1 = sma(close, fastMA) > sma(close, slowMA)
bolSigTrendLO2 = close > sma(close,fastMA)
bolSigTrendLO3 = bolSigTrendLO1 and bolSigTrendLO2

bolSigTrendLC1 = sma(close, fastMA) < sma(close, slowMA)
bolSigTrendLC2 = close < sma(close, fastMA)
bolSigTrendLC3 = bolSigTrendLC1 and bolSigTrendLC2

bolSigTrendSO1 = bolSigTrendLC3
bolSigTrendSC1 = bolSigTrendLO1

bolLongOpenTS = bolSigTrendLO3 and bolFilter_TS1
bolLongCloseTS = bolSigTrendLC3 and bolFilter_TS3

bolShortOpenTS = bolSigTrendSO1 and bolFilter_TS3
bolShortCloseTS = bolLongOpenTS and bolFilter_TS1

plot(sma(close, fastMA), title='FastMA', color=color.green, linewidth=2, style=plot.style_line)  // plot FastMA
plot(sma(close, slowMA), title='SlowMA', color=color.red, linewidth=2, style=plot.style_line)  // plot SlowMA



    //  > BREAKOUT <
flFilter_BS1 = 0.5 * stdev(close,slowMA)[1]
bolFilter_BS2 = volume > sma(volume,slowMA)*1.25

bolSigBreakoutLO1 = close > (highestbars(high,slowMA)[1] + flFilter_BS1)
bolSigBreakoutLC1 = barssince(bolSigBreakoutLO1)==5

bolSigBreakoutSO1 = close < lowestbars(low,slowMA)[1] - flFilter_BS1
bolSigBreakoutSC1 = barssince(bolSigBreakoutSO1)==5


bolLongOpenBO = bolSigBreakoutLO1 and bolFilter_BS2
bolLongCloseBO = bolSigBreakoutLC1

bolShortOpenBO = bolSigBreakoutSO1 and bolFilter_BS2
bolShortCloseBO = bolSigBreakoutSC1

//=== STRATEGIES ENTRIES & EXITS ===
    //  > STOPS & LIMITS <
stop_level_Long = strategy.position_avg_price * (1 - flStopLoss)
take_level_Long = strategy.position_avg_price * (1 + flTakeProfit)
stop_level_Short = strategy.position_avg_price * (1 + flStopLoss)
take_level_Short = strategy.position_avg_price * (1 - flTakeProfit)

    //  > ENTRIES / CLOSES / EXITS <
if window() //only in backtest-window
    if (bolOS == true)
        if (intTrend == 0)
            if(strStrategy == "Long" or strStrategy == "Long & Short")
                strategy.entry("Lng Osc", strategy.long, when=bolLongOpenOS)  // buy long when "within window of time" AND crossover
            if(strStrategy == "Short" or strStrategy == "Long & Short")
                strategy.entry("Short Osc", strategy.short, when=bolShortOpenOS)
        strategy.close("Lng Osc", when=(bolLongCloseOS))
        //strategy.exit("Exit L OS/STD", "Lng Osc", stop = strategy.position_avg_price - 2*stdev(close,10))
        strategy.exit("Exit L OS/%", "Lng Osc", stop=stop_level_Long)
        strategy.close("Short Osc", when=(bolShortCloseOS))
        //strategy.exit("Exit S OS/STD", "Short Osc", stop = strategy.position_avg_price + 2*stdev(strategy.position_avg_price,10))
        strategy.exit("Exit S OS/%", "Short Osc", stop=stop_level_Short)
    if (bolTS == true)
        if (not(intTrend == 0))
            if((strStrategy == "Long") or (strStrategy == "Long & Short"))
                strategy.entry("Lng TD", strategy.long, when=bolLongOpenTS)  // buy long when "within window of time" AND crossover
            if((strStrategy == "Short") or (strStrategy == "Long & Short"))
                strategy.entry("Short TD", strategy.short, when=(bolShortOpenTS and bolTS))  // buy long when "within window of time" AND crossover
        strategy.exit("Exit L TD", "Lng TD", stop=stop_level_Long)
        strategy.close("Lng TD", when=bolLongCloseTS)
        strategy.exit("Exit S TD", "Short TD", stop=stop_level_Short)
        strategy.close("Short TD", when=bolShortCloseTS)
    if (bolBO == true)
        if((strStrategy == "Long") or (strStrategy == "Long & Short"))
            strategy.entry("Lng BO", strategy.long, when=bolLongOpenBO)  // buy long when "within window of time" AND crossover
            strategy.close("Lng BO", when=bolLongCloseBO)
            //strategy.exit("Exit L BO/STD", "Lng BO", stop = strategy.position_avg_price - 2*stdev(strategy.position_avg_price,10))
            strategy.exit("Exit L BO/2.5%", "Lng BO", stop=stop_level_Long)
        if((strStrategy == "Short") or (strStrategy == "Long & Short"))
            strategy.entry("Short BO", strategy.short, when=bolShortOpenBO)  // buy long when "within window of time" AND crossover
            strategy.close("Short BO", when=bolShortCloseBO)
            //strategy.exit("Exit S BO/STD", "Short BO", stop = strategy.position_avg_price - 2*stdev(strategy.position_avg_price,10))
            strategy.exit("Exit S BO/%", "Short BO", stop=stop_level_Short)




Mehr