Strategie zur Umkehrung der Doppelkanalverfolgung

Schriftsteller:ChaoZhang, Datum: 2023-11-02 16:31:50
Tags:

img

Übersicht

Die Dual Channel Tracking Reversal-Strategie ist eine Umkehrhandelsstrategie, die Bollinger-Bänder, Keltner-Kanäle und Momentum-Indikatoren kombiniert.

Strategie Logik

  1. Berechnung der mittleren, oberen und unteren Bands für Bollinger-Bänder

    • Mittlere Band verwendet SMA von nahe
    • Die oberen und unteren Bands sind mittlere Band ± einstellbares Standardabweichungsvielfaches
  2. Berechnung der mittleren, oberen und unteren Bands für Keltner-Kanäle

    • Mittlere Band verwendet SMA von nahe
    • Die oberen und unteren Bands sind mittlere Band ± einstellbares ATR-Multiplikator
  3. Bestimmen Sie, ob sich Bollinger-Bänder innerhalb der Keltner-Kanäle befinden

    • Anpressen, wenn unterer BB > unterer KC und oberer BB < oberer KC
    • Wenn nicht, dann schnapp dich ab.
  4. Berechnen Sie die lineare Regressionsneigung von BB und KC

    • Val > 0 zeigt an, dass die Schließung zunimmt, val < 0 bedeutet, dass sie abnimmt
  5. Berechnung des ROC und des EMA von ROC für den Abschluss

    • Bestimmung, ob die Änderungsrate den verstellbaren Schwellenwert übersteigt
    • Über dem Schwellenwert zeigt ein bestehender Trend an
  6. Bei Druck, lang, wenn Val > 0 und ROC den Schwellenwert überschreitet

    • Umgekehrt für kurz
  7. Festlegen von Stop-Loss- und Take-Profit-Bedingungen

Vorteile

  1. Verbesserte Genauigkeit durch Kombination eines Doppelkanalsystems zur Umkehrung

  2. Vermeiden Sie falsche Signale mit linearer Regression und Veränderungsrate

  3. Flexible, einstellbare Parameter für die Produktoptimierung

  4. Wirksame Risikokontrolle pro Handel mit Stop-Loss/Take-Profit

  5. Ausreichende Daten aus Backtests zur Validierung der Rentabilität der Strategie

Risiken und Lösungen

  1. Das Pressen führt nicht immer zu einer wirksamen Umkehrung

    • Optimierung der Parameter und Verschärfung der Druckkriterien
  2. Falsche Ausbrüche erzeugen falsche Signale.

    • Hinzufügen von linearer Regression zur Bestimmung der Trendrichtung
  3. Zu großer Stop-Loss, der zu einem übermäßigen Einzelverlust führt

    • Optimieren Sie Stop-Loss-Punkte und Kontrolle pro Handelsverlust
  4. Unzureichende Prüfzeiten

    • Erweiterung der Tests auf mehr Zeiträume, um die Langzeitfähigkeit zu beweisen

Möglichkeiten zur Verbesserung

  1. Optimierung der Parameter für mehr Produkte

  2. Hinzufügen von maschinellem Lernen zur Unterstützung/Widerstandsidentifizierung

  3. Einbeziehung von Volumenänderungen zur Verbesserung der Breakout-Gültigkeit

  4. Durchführung einer mehrzeitlichen Analyse zur Feststellung der Trendbeständigkeit

  5. Optimieren dynamischer Stop-Loss/Take-Profit

Schlussfolgerung

Die Dual Channel Tracking Reversal Strategie nutzt Indikatoren wie Bollinger Bands und Keltner Channels für den Umkehrhandel. Mit Parameteroptimierung kann sie auf verschiedene Produkte angepasst werden, um die Breakout-Gültigkeit bis zu einem gewissen Grad zu identifizieren.


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

//@version=4
// Credit for the initial Squeeze Momentum code to LazyBear, rate of change code is from Kiasaki
strategy("Squeeze X BF 🚀", overlay=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.0)

/////////////// Time Frame ///////////////
testStartYear = input(2012, "Backtest Start Year") 
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay, 0, 0)

testStopYear = input(2019, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay, 0, 0)

testPeriod() => true

/////////////// Squeeeeze ///////////////
length = input(20, title="BB Length")
mult = input(2.0,title="BB MultFactor")
lengthKC=input(22, title="KC Length")
multKC = input(1.5, title="KC MultFactor")
 
useTrueRange = input(true, title="Use TrueRange (KC)")
 
// Calculate BB
source = close
basis = sma(source, length)
dev = mult * stdev(source, length)
upperBB = basis + dev
lowerBB = basis - dev

// Calculate KC
ma = sma(source, lengthKC)
range = useTrueRange ? tr : (high - low)
rangema = sma(range, lengthKC)
upperKC = ma + rangema * multKC
lowerKC = ma - rangema * multKC

sqzOn  = (lowerBB > lowerKC) and (upperBB < upperKC)
sqzOff = (lowerBB < lowerKC) and (upperBB > upperKC)
noSqz  = (sqzOn == false) and (sqzOff == false)

val = linreg(source - avg(avg(highest(high, lengthKC), lowest(low, lengthKC)),sma(close,lengthKC)), lengthKC,0)

///////////// Rate Of Change ///////////// 
roclength = input(30, minval=1), pcntChange = input(7, minval=1)
roc = 100 * (source - source[roclength]) / source[roclength]
emaroc = ema(roc, roclength / 2)
isMoving() => emaroc > (pcntChange / 2) or emaroc < (0 - (pcntChange / 2))

/////////////// Strategy ///////////////
long = val > 0 and isMoving()
short = val < 0 and isMoving()

last_long = 0.0
last_short = 0.0
last_long := long ? time : nz(last_long[1])
last_short := short ? time : nz(last_short[1])

long_signal = crossover(last_long, last_short)
short_signal = crossover(last_short, last_long)

last_open_long_signal = 0.0
last_open_short_signal = 0.0
last_open_long_signal := long_signal ? open : nz(last_open_long_signal[1])
last_open_short_signal := short_signal ? open : nz(last_open_short_signal[1])

last_long_signal = 0.0
last_short_signal = 0.0
last_long_signal := long_signal ? time : nz(last_long_signal[1])
last_short_signal := short_signal ? time : nz(last_short_signal[1])

in_long_signal = last_long_signal > last_short_signal
in_short_signal = last_short_signal > last_long_signal

last_high = 0.0
last_low = 0.0
last_high := not in_long_signal ? na : in_long_signal and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_short_signal ? na : in_short_signal and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])

sl_inp = input(100.0, title='Stop Loss %') / 100
tp_inp = input(5000.0, title='Take Profit %') / 100
 
take_level_l = strategy.position_avg_price * (1 + tp_inp)
take_level_s = strategy.position_avg_price * (1 - tp_inp)

since_longEntry = barssince(last_open_long_signal != last_open_long_signal[1]) 
since_shortEntry = barssince(last_open_short_signal != last_open_short_signal[1]) 

slLong = in_long_signal ? strategy.position_avg_price * (1 - sl_inp) : na
slShort = strategy.position_avg_price * (1 + sl_inp)
long_sl = in_long_signal ? slLong : na
short_sl = in_short_signal ? slShort : na

/////////////// Execution ///////////////
if testPeriod()
    strategy.entry("Long",  strategy.long, when=long)
    strategy.entry("Short", strategy.short, when=short)
    strategy.exit("Long Ex", "Long", stop=long_sl, limit=take_level_l, when=since_longEntry > 0)
    strategy.exit("Short Ex", "Short", stop=short_sl, limit=take_level_s, when=since_shortEntry > 0)
    
/////////////// Plotting ///////////////
bcolor = iff(val > 0, iff(val > nz(val[1]), color.lime, color.green), iff(val < nz(val[1]), color.red, color.maroon))
plot(val, color=bcolor, linewidth=4)
bgcolor(not isMoving() ? color.white : long ? color.lime : short ? color.red : na, transp=70)
bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=50)
hline(0, color = color.white)

Mehr