Handelsstrategie mit bidirektionaler gleitender Durchschnittsregression


Erstellungsdatum: 2024-01-15 12:15:14 zuletzt geändert: 2024-01-15 12:15:14
Kopie: 0 Klicks: 670
1
konzentrieren Sie sich auf
1617
Anhänger

Handelsstrategie mit bidirektionaler gleitender Durchschnittsregression

Überblick

Die Bidirectional Moving Average Reversion Trading Strategy ist eine quantitative Handelsstrategie, die auf dem Prinzip der durchschnittlichen Preisreversion basiert. Die Strategie erfasst die Preisreversionschancen durch die Einrichtung mehrerer Gruppen von Moving Averages.

Strategieprinzip

Die Strategie basiert hauptsächlich auf der Theorie der durchschnittlichen Rückkehr der Preise. Sie besagt, dass die Preise immer um eine durchschnittliche Schwankung herum liegen, und wenn die Preise stark von der Durchschnittlichkeit abweichen, ist es wahrscheinlicher, dass sie zur Mittelwert zurückkehren. Insbesondere setzt die Strategie gleichzeitig drei Gruppen von Mittellinien auf: die Eröffnungsmittellinie, die Schadensmittellinie und die Schadensmittellinie.

Aus der Code-Logik betrachtet, ist die Open-Position-Mittellinie in Multi-Line und Short-Line unterteilt, die jeweils aus Long- und Short-Line bestehen. Die Abweichung zwischen ihnen und dem Preis bestimmt die Größe der Position. Außerdem ist die Off-Position-Mittellinie eine separate Mittellinie, die verwendet wird, um den Zeitpunkt der Off-Position zu bestimmen.

Analyse der Stärken

Die Vorteile einer bi-directionalen Mittellinien-Rückkehrstrategie bestehen hauptsächlich aus:

  1. Der Preiswechsel wurde als Trendbewertung erfasst.
  2. Risikokontrolle durch Grenzverluste
  3. Anpassungsfähige Kombinationen von Parametern
  4. Einfach zu verstehen und die Parameter optimieren

Die Strategie ist für Sorten mit geringer Volatilität und geringer Preisspanne geeignet, insbesondere für Sorten, die in die Ausgleichsphase eintreten. Sie kann die Gelegenheit einer vorübergehenden Preisumkehr effektiv erfassen. Gleichzeitig sind die Risikokontrollmaßnahmen der Strategie so ausgereift, dass die Verluste in einem bestimmten Umfang kontrolliert werden können, auch wenn der Preis nicht zurückkehrt.

Risikoanalyse

Die Strategie der bilateralen Gleichgewichtsrückkehr birgt einige Risiken:

  1. Die Strategie besteht in der Gefahr, dass bei einem Aufprall die Positionen in Folge geöffnet werden und die Positionen schließlich platzen.
  2. Wenn die Preisschwankungen zu groß sind, kann die Position bis zum Limit-Verlust erreicht werden und zwangsweise platziert werden.
  3. Die Einstellung der Parameter dieser Strategie hat einen wichtigen Einfluss auf ihre Profitabilität, und wenn die Parameter nicht richtig eingestellt werden, kann die Gewinnwahrscheinlichkeit erheblich reduziert werden.

Für die oben genannten Risiken können Optimierungen in folgenden Bereichen vorgenommen werden:

  1. Ein weiterer Grund, warum es so ist, ist, dass es nicht so häufig ist, wie es geplant ist.
  2. Positionsverkleinerung zur Verhinderung von Ausbruchrisiken
  3. Optimierung von Parametern wie Durchschnittszyklus und Schadenfrequenz

Optimierungsrichtung

Die Strategie bietet auch viel Optimierungsmöglichkeiten, hauptsächlich aus folgenden Perspektiven:

  1. Erhöhung der Logik der Eröffnungsbedingungen zur Verhinderung von Rückschlägen bei Trends
  2. Hinzugefügt wird die Logik der Positionssenkung, um die Risiken von Preisschwankungen zu vermeiden.
  3. Versuche verschiedene Arten von Mittellinien, um eine bessere Kombination von Parametern zu finden
  4. Automatische Optimierung von Parametern mit Hilfe von maschinellen Lernverfahren
  5. Erhöhung der automatischen Stop-Loss-Strategie und bessere Risikokontrolle

Zusammenfassen

Die Strategie der bilateralen Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung der Erhöhung

Strategiequellcode
/*backtest
start: 2023-12-15 00:00:00
end: 2024-01-14 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy(title = "hamster-bot MRS 2", overlay = true, default_qty_type = strategy.percent_of_equity, initial_capital = 100, default_qty_value = 30, pyramiding = 1, commission_value = 0.1, backtest_fill_limits_assumption = 1)
info_options = "Options"

on_close = input(false, title = "Entry on close", inline=info_options, group=info_options)
OFFS = input.int(0, minval = 0, maxval = 1, title = "| Offset View", inline=info_options, group=info_options)
trade_offset = input.int(0, minval = 0, maxval = 1, title = "Trade", inline=info_options, group=info_options)
use_kalman_filter = input.bool(false, title="Use Kalman filter", group=info_options)

//MA Opening
info_opening = "MA Opening Long"
maopeningtyp_l = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_opening, group=info_opening)
maopeningsrc_l = input.source(ohlc4, title = "", inline=info_opening, group=info_opening)
maopeninglen_l = input.int(3, minval = 1, title = "", inline=info_opening, group=info_opening)
long1on    = input(true, title = "", inline = "long1")
long1shift = input.float(0.96, step = 0.005, title = "Long", inline = "long1")
long1lot   = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "long1")

info_opening_s = "MA Opening Short"
maopeningtyp_s = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_opening_s, group=info_opening_s)
maopeningsrc_s = input.source(ohlc4, title = "", inline=info_opening_s, group=info_opening_s)
maopeninglen_s = input.int(3, minval = 1, title = "", inline=info_opening_s, group=info_opening_s)
short1on    = input(true, title = "", inline = "short1")
short1shift = input.float(1.04, step = 0.005, title = "short", inline = "short1")
short1lot   = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "short1")


//MA Closing
info_closing = "MA Closing"
maclosingtyp = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_closing, group=info_closing)
maclosingsrc = input.source(ohlc4, title = "", inline=info_closing, group=info_closing)
maclosinglen = input.int(3, minval = 1, maxval = 200, title = "", inline=info_closing, group=info_closing)
maclosingmul = input.float(1, step = 0.005, title = "mul", inline=info_closing, group=info_closing)

startTime = input(timestamp("01 Jan 2010 00:00 +0000"), "Start date", inline = "period")
finalTime = input(timestamp("31 Dec 2030 23:59 +0000"), "Final date", inline = "period")

HMA(_src, _length) =>  ta.wma(2 * ta.wma(_src, _length / 2) - ta.wma(_src, _length), math.round(math.sqrt(_length)))
EHMA(_src, _length) =>  ta.ema(2 * ta.ema(_src, _length / 2) - ta.ema(_src, _length), math.round(math.sqrt(_length)))
THMA(_src, _length) =>  ta.wma(ta.wma(_src,_length / 3) * 3 - ta.wma(_src, _length / 2) - ta.wma(_src, _length), _length)
tema(sec, length)=>
    tema1= ta.ema(sec, length)
    tema2= ta.ema(tema1, length)
    tema3= ta.ema(tema2, length)
    tema_r = 3*tema1-3*tema2+tema3
donchian(len) => math.avg(ta.lowest(len), ta.highest(len))
ATR_func(_src, _len)=>
    atrLow = low - ta.atr(_len)
    trailAtrLow = atrLow
    trailAtrLow := na(trailAtrLow[1]) ? trailAtrLow : atrLow >= trailAtrLow[1] ? atrLow : trailAtrLow[1]
    supportHit = _src <= trailAtrLow
    trailAtrLow := supportHit ? atrLow : trailAtrLow
    trailAtrLow
f_dema(src, len)=>
    EMA1 = ta.ema(src, len)
    EMA2 = ta.ema(EMA1, len)
    DEMA = (2*EMA1)-EMA2
f_zlema(src, period) =>
    lag = math.round((period - 1) / 2)
    ema_data = src + (src - src[lag])
    zl= ta.ema(ema_data, period)
f_kalman_filter(src) =>
    float value1= na
    float value2 = na
    value1 := 0.2 * (src - src[1]) + 0.8 * nz(value1[1])
    value2 := 0.1 * (ta.tr) + 0.8 * nz(value2[1])
    lambda = math.abs(value1 / value2)
    alpha = (-math.pow(lambda, 2) + math.sqrt(math.pow(lambda, 4) + 16 * math.pow(lambda, 2)))/8
    value3 = float(na)
    value3 := alpha * src + (1 - alpha) * nz(value3[1])
//SWITCH
ma_func(modeSwitch, src, len, use_k_f=true) =>
      modeSwitch == "SMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.sma(src, len))  : ta.sma(src, len) :
      modeSwitch == "RMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.rma(src, len))  : ta.rma(src, len) :
      modeSwitch == "EMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.ema(src, len))  : ta.ema(src, len) :
      modeSwitch == "TEMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(tema(src, len))    : tema(src, len):
      modeSwitch == "DEMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(f_dema(src, len))  : f_dema(src, len):
      modeSwitch == "ZLEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(f_zlema(src, len)) : f_zlema(src, len):
      modeSwitch == "WMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.wma(src, len))  : ta.wma(src, len):
      modeSwitch == "VWMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.vwma(src, len)) : ta.vwma(src, len):
      modeSwitch == "Hma"   ? use_kalman_filter and use_k_f ? f_kalman_filter(HMA(src, len))     : HMA(src, len):
      modeSwitch == "Ehma"  ? use_kalman_filter and use_k_f ? f_kalman_filter(EHMA(src, len))    : EHMA(src, len):
      modeSwitch == "Thma"  ? use_kalman_filter and use_k_f ? f_kalman_filter(THMA(src, len/2))  : THMA(src, len/2):
      modeSwitch == "ATR"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ATR_func(src, len)): ATR_func(src, len) :
      modeSwitch == "L"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.lowest(len)): ta.lowest(len) :
      modeSwitch == "H"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.highest(len)): ta.highest(len) :
      modeSwitch == "DMA"   ? donchian(len) : na

//Var
sum = 0.0
maopening_l = 0.0
maopening_s = 0.0
maclosing = 0.0
pos = strategy.position_size
p = 0.0
p := pos == 0 ? (strategy.equity / 100) / close : p[1]
truetime = true
loss = 0.0
maxloss = 0.0
equity = 0.0

//MA Opening
maopening_l := ma_func(maopeningtyp_l, maopeningsrc_l, maopeninglen_l)
maopening_s := ma_func(maopeningtyp_s, maopeningsrc_s, maopeninglen_s)

//MA Closing
maclosing := ma_func(maclosingtyp, maclosingsrc, maclosinglen) * maclosingmul

long1 = long1on == false ? 0 : long1shift == 0 ? 0 : long1lot == 0 ? 0 : maopening_l == 0 ? 0 : maopening_l * long1shift
short1 = short1on == false ? 0 : short1shift == 0 ? 0 : short1lot == 0 ? 0 : maopening_s == 0 ? 0 : maopening_s * short1shift
//Colors
long1col = long1 == 0 ? na : color.green
short1col = short1 == 0 ? na : color.red
//Lines
// plot(maopening_l, offset = OFFS, color = color.new(color.green, 50))
// plot(maopening_s, offset = OFFS, color = color.new(color.red, 50))
plot(maclosing, offset = OFFS, color = color.fuchsia)
long1line = long1 == 0 ? close : long1
short1line = short1 == 0 ? close : short1
plot(long1line, offset = OFFS, color = long1col)
plot(short1line, offset = OFFS, color = short1col)

//Lots
lotlong1 = p * long1lot
lotshort1 = p * short1lot

//Entry
if truetime
    //Long
    sum := 0
    strategy.entry("L", strategy.long, lotlong1, limit = on_close ? na : long1, when = long1 > 0 and pos <= sum and (on_close ? close <= long1[trade_offset] : true))
    sum := lotlong1

    //Short
    sum := 0
    pos := -1 * pos
    strategy.entry("S", strategy.short, lotshort1, limit = on_close ? na : short1, when = short1 > 0 and pos <= sum and (on_close ? close >= short1[trade_offset] : true))
    sum := lotshort1

strategy.exit("Exit", na, limit = maclosing)
if time > finalTime
    strategy.close_all()