Die Ressourcen sind geladen. Beförderung...

Strategie für den adaptiven gleitenden Durchschnitt des Gauss-Kanals

Schriftsteller:ChaoZhang, Datum: 2024-03-28 18:08:18
Tags:

img

Übersicht

Die Gaussian Channel Adaptive Moving Average Strategy ist eine quantitative Handelsstrategie, die Gaussian Filtering Techniken und adaptive Parameter-Einstellungen nutzt. Basierend auf der von John Ehlers vorgeschlagenen Gaussian Filter-Theorie erzeugt diese Strategie reibungslose und adaptive Handelssignale, indem mehrere exponentielle gleitende Durchschnittsberechnungen auf Preisdaten angewendet werden. Der Kern der Strategie besteht darin, einen dynamisch angepassten Preiskanal zu konstruieren, mit oberen und unteren Bands, die durch Hinzufügen und Subtrahieren des gefilterten wahren Bereichs des Gaussian-filterten Preises erhalten werden. Wenn der Preis über das obere Band bricht, wird eine Long-Position eingegeben, und wenn er das untere Band bricht, wird eine Short-Position eingegeben. Darüber hinaus führt die Strategie zeitliche Perioden-Einstellungen ein, die flexible Einstellungen für die Anfangs- und Endzeiten der Strategieausführung ermöglichen, wodurch ihre Prak

Strategieprinzipien

Die Grundsätze der Adaptive Moving Average-Strategie des Gauss-Kanals sind wie folgt:

  1. Berechnen Sie den Gauss-Filterwert des Preises. Basierend auf der vom Benutzer definierten Probenahmezeit und der Anzahl der Pole werden die Beta- und Alpha-Parameter berechnet, und dann werden die Preisdaten einem mehrstufigen Gauss-Filter unterzogen, um eine glättete Preisreihe zu erhalten.
  2. Berechnen Sie den Gauss-Filterwert des wahren Bereichs. Der gleiche Gauss-Filterprozess wird auf den wahren Bereich des Preises angewendet, was zu einer glätteten Bereichsreihe führt.
  3. Der durch Gauss gefilterte Preis dient als mittleres Band, das obere Band wird durch Hinzufügen des Produktes des gefilterten wahren Bereichs und eines vom Benutzer definierten Multiplikators zum mittleren Band gebildet, und das untere Band wird gebildet, indem dieser Wert vom mittleren Band subtrahiert wird, wodurch ein dynamischer Kanal erstellt wird.
  4. Wenn der Preis über das obere Band des Kanals bricht, wird ein Kaufsignal erzeugt; wenn der Preis unter das untere Band bricht, wird ein Verkaufssignal erzeugt.
  5. Die Benutzer können die Start- und Endzeiten für die Strategieausführung festlegen, und die Strategie wird nur auf der Grundlage von Handelssignalen innerhalb dieser angegebenen Zeitspanne betrieben.

Analyse der Vorteile

Die Strategie des adaptiven gleitenden Durchschnitts des Gauss-Kanals hat folgende Vorteile:

  1. Die Strategie verwendet dynamisch angepasste Parameter, die sich an unterschiedliche Marktbedingungen und Handelsinstrumente anpassen können, ohne häufige manuelle Anpassungen erforderlich zu machen.
  2. Durch den Aufbau von Preiskanälen kann die Strategie Markttrends effektiv erfassen und verfolgen und falsche Signale in unruhigen Märkten vermeiden.
  3. Die Gauss-Filtertechnik wird verwendet, um die Preisdaten mehrmals zu glätten, wodurch die meisten Marktgeräusche beseitigt und Handelssignale zuverlässiger werden.
  4. Hohe Flexibilität: Die Benutzer können die Strategieparameter entsprechend ihren Bedürfnissen wie die Probenahmezeit, die Anzahl der Pole, den Bereichsmultiplier usw. anpassen, um die Leistung der Strategie zu optimieren.
  5. Durch die Einführung von Zeitrahmenparametern kann die Strategie innerhalb eines bestimmten Zeitrahmens ausgeführt werden, was die Anwendung in der realen Welt und die Forschung im Rahmen von Backtests erleichtert.

Risikoanalyse

Trotz seiner vielen Vorteile birgt die Adaptive Moving Average-Strategie des Gauss-Kanals immer noch bestimmte Risiken:

  1. Unangemessene Parameter-Einstellungen können zu einer Strategieunwirksamkeit oder schlechter Leistung führen und wiederholte Tests und Optimierungen in praktischen Anwendungen erfordern.
  2. Das Risiko plötzlicher Ereignisse: Angesichts bestimmter plötzlicher größerer Ereignisse kann die Strategie möglicherweise nicht rechtzeitig richtig reagieren, was zu Verlusten führt.
  3. Wenn die Parameter-Einstellungen zu eng an historische Daten angepasst werden, kann die Strategie in Zukunft eine schlechte Leistung erbringen, so dass sowohl die Leistung innerhalb der Stichprobe als auch die Leistung außerhalb der Stichprobe berücksichtigt werden müssen.
  4. Die Strategie eignet sich hauptsächlich für Trendmärkte, und häufiger Handel in unruhigen Märkten kann mit erheblichen Arbitragerisiken konfrontiert sein.

Optimierungsrichtlinien

Die Optimierungsrichtlinien für die Adaptive Moving Average-Strategie des Gauss-Kanals umfassen:

  1. Dynamische Parameteroptimierung: Durch die Einführung von maschinellem Lernen und anderen Techniken wird eine automatische Optimierung und dynamische Anpassung der Strategieparameter erreicht, um die Anpassungsfähigkeit zu verbessern.
  2. Multi-Faktor-Fusion: Kombination anderer effektiver technischer Indikatoren oder Faktoren mit dem Gauss-Kanal, um robustere Handelssignale zu bilden.
  3. Optimierung des Positionsmanagements: Einbeziehung vernünftiger Positionsmanagement- und Geldmanagementregeln in die Strategie zur Kontrolle von Rücknahmen und Risiken.
  4. Koordinierung auf mehreren Instrumenten: Erweitern Sie die Strategie auf mehrere verschiedene Handelsinstrumente und diversifizieren Sie die Risiken durch Vermögensverteilung und Korrelationsanalyse.

Zusammenfassung

Die Adaptive Moving Average-Strategie ist eine quantitative Handelsstrategie, die auf Gauss-Filterung und adaptiven Parametern basiert und durch dynamische Konstruktion von Preiskanälen reibungslose und zuverlässige Handelssignale erzeugt. Die Strategie hat Vorteile wie starke Anpassungsfähigkeit, gute Trendverfolgungsfähigkeit, hohe Geschmeidigkeit, große Flexibilität und starke Praktikabilität. Sie ist jedoch auch mit Risiken wie Parametersetzung, plötzlichen Ereignissen, Überanpassung und Arbitrage konfrontiert. In Zukunft kann die Strategie durch dynamische Parameteroptimierung, Multi-Faktor-Fusion, Positionsmanagementoptimierung und Multi-Instrument-Koordination weiter verfeinert und verbessert werden.


/*backtest
start: 2023-03-22 00:00:00
end: 2024-03-27 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy(title="Gaussian Channel Strategy v1.0", overlay=true, calc_on_every_tick=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1)

// Date condition inputs
startDate = input(title="Date Start", type=input.time, defval=timestamp("1 Jan 2018 00:00 +0000"), group="Dates")
endDate = input(title="Date End", type=input.time, defval=timestamp("31 Dec 2060 23:59 +0000"), group="Dates")
timeCondition = true

// This study is an experiment utilizing the Ehlers Gaussian Filter technique combined with lag reduction techniques and true range to analyze trend activity.
// Gaussian filters, as Ehlers explains it, are simply exponential moving averages applied multiple times.
// First, beta and alpha are calculated based on the sampling period and number of poles specified. The maximum number of poles available in this script is 9.
// Next, the data being analyzed is given a truncation option for reduced lag, which can be enabled with "Reduced Lag Mode".
// Then the alpha and source values are used to calculate the filter and filtered true range of the dataset.
// Filtered true range with a specified multiplier is then added to and subtracted from the filter, generating a channel.
// Lastly, a one pole filter with a N pole alpha is averaged with the filter to generate a faster filter, which can be enabled with "Fast Response Mode". 

//Custom bar colors are included.

//Note: Both the sampling period and number of poles directly affect how much lag the indicator has, and how smooth the output is.
//      Larger inputs will result in smoother outputs with increased lag, and smaller inputs will have noisier outputs with reduced lag.
//      For the best results, I recommend not setting the sampling period any lower than the number of poles + 1. Going lower truncates the equation.

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Updates:
// Huge shoutout to @e2e4mfck for taking the time to improve the calculation method!
// -> migrated to v4
// -> pi is now calculated using trig identities rather than being explicitly defined.
// -> The filter calculations are now organized into functions rather than being individually defined.
// -> Revamped color scheme.

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions - courtesy of @e2e4mfck
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
 
//Filter function 
f_filt9x (_a, _s, _i) => 
    int _m2 = 0, int _m3 = 0, int _m4 = 0, int _m5 = 0, int _m6 = 0, 
    int _m7 = 0, int _m8 = 0, int _m9 = 0, float _f = .0, _x = (1 - _a)
    // Weights. 
    // Initial weight _m1 is a pole number and equal to _i
    _m2 := _i == 9 ? 36  : _i == 8 ? 28 : _i == 7 ? 21 : _i == 6 ? 15 : _i == 5 ? 10 : _i == 4 ? 6 : _i == 3 ? 3 : _i == 2 ? 1 : 0
    _m3 := _i == 9 ? 84  : _i == 8 ? 56 : _i == 7 ? 35 : _i == 6 ? 20 : _i == 5 ? 10 : _i == 4 ? 4 : _i == 3 ? 1 : 0
    _m4 := _i == 9 ? 126 : _i == 8 ? 70 : _i == 7 ? 35 : _i == 6 ? 15 : _i == 5 ? 5  : _i == 4 ? 1 : 0
    _m5 := _i == 9 ? 126 : _i == 8 ? 56 : _i == 7 ? 21 : _i == 6 ? 6  : _i == 5 ? 1  : 0 
    _m6 := _i == 9 ? 84  : _i == 8 ? 28 : _i == 7 ? 7  : _i == 6 ? 1  : 0 
    _m7 := _i == 9 ? 36  : _i == 8 ? 8  : _i == 7 ? 1  : 0 
    _m8 := _i == 9 ? 9   : _i == 8 ? 1  : 0 
    _m9 := _i == 9 ? 1   : 0
    // filter
    _f :=   pow(_a, _i) * nz(_s) + 
      _i  *     _x      * nz(_f[1])      - (_i >= 2 ? 
      _m2 * pow(_x, 2)  * nz(_f[2]) : 0) + (_i >= 3 ? 
      _m3 * pow(_x, 3)  * nz(_f[3]) : 0) - (_i >= 4 ? 
      _m4 * pow(_x, 4)  * nz(_f[4]) : 0) + (_i >= 5 ? 
      _m5 * pow(_x, 5)  * nz(_f[5]) : 0) - (_i >= 6 ? 
      _m6 * pow(_x, 6)  * nz(_f[6]) : 0) + (_i >= 7 ? 
      _m7 * pow(_x, 7)  * nz(_f[7]) : 0) - (_i >= 8 ? 
      _m8 * pow(_x, 8)  * nz(_f[8]) : 0) + (_i == 9 ? 
      _m9 * pow(_x, 9)  * nz(_f[9]) : 0)

//9 var declaration fun
f_pole (_a, _s, _i) =>
    _f1 =            f_filt9x(_a, _s, 1),      _f2 = (_i >= 2 ? f_filt9x(_a, _s, 2) : 0), _f3 = (_i >= 3 ? f_filt9x(_a, _s, 3) : 0)
    _f4 = (_i >= 4 ? f_filt9x(_a, _s, 4) : 0), _f5 = (_i >= 5 ? f_filt9x(_a, _s, 5) : 0), _f6 = (_i >= 6 ? f_filt9x(_a, _s, 6) : 0)
    _f7 = (_i >= 2 ? f_filt9x(_a, _s, 7) : 0), _f8 = (_i >= 8 ? f_filt9x(_a, _s, 8) : 0), _f9 = (_i == 9 ? f_filt9x(_a, _s, 9) : 0)
    _fn = _i == 1 ? _f1 : _i == 2 ? _f2 : _i == 3 ? _f3 :
      _i == 4     ? _f4 : _i == 5 ? _f5 : _i == 6 ? _f6 :
      _i == 7     ? _f7 : _i == 8 ? _f8 : _i == 9 ? _f9 : na
    [_fn, _f1]

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Source
src = input(defval=hlc3, title="Source")

//Poles
int N = input(defval=4, title="Poles", minval=1, maxval=9)

//Period
int per = input(defval=144, title="Sampling Period", minval=2)

//True Range Multiplier
float mult = input(defval=1.414, title="Filtered True Range Multiplier", minval=0)

//Lag Reduction
bool modeLag  = input(defval=false, title="Reduced Lag Mode")
bool modeFast = input(defval=false, title="Fast Response Mode")

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Beta and Alpha Components
beta  = (1 - cos(4*asin(1)/per)) / (pow(1.414, 2/N) - 1)
alpha = - beta + sqrt(pow(beta, 2) + 2*beta)

//Lag
lag = (per - 1)/(2*N)

//Data
srcdata = modeLag ? src + (src - src[lag]) : src
trdata  = modeLag ? tr(true) + (tr(true) - tr(true)[lag]) : tr(true)

//Filtered Values
[filtn, filt1]     = f_pole(alpha, srcdata, N)
[filtntr, filt1tr] = f_pole(alpha, trdata,  N)

//Lag Reduction
filt   = modeFast ? (filtn + filt1)/2 : filtn
filttr = modeFast ? (filtntr + filt1tr)/2 : filtntr

//Bands
hband = filt + filttr*mult
lband = filt - filttr*mult

// Colors
color1   = #0aff68
color2   = #00752d
color3   = #ff0a5a
color4   = #990032
fcolor   = filt > filt[1] ? #0aff68 : filt < filt[1] ? #ff0a5a : #cccccc
barcolor = (src > src[1]) and (src > filt) and (src < hband) ? #0aff68 : (src > src[1]) and (src >= hband) ? #0aff1b : (src <= src[1]) and (src > filt) ? #00752d : 
           (src < src[1]) and (src < filt) and (src > lband) ? #ff0a5a : (src < src[1]) and (src <= lband) ? #ff0a11 : (src >= src[1]) and (src < filt) ? #990032 : #cccccc

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Plot
filtplot = plot(filt, title="Filter", color=fcolor, linewidth=3)

//Band Plots
hbandplot = plot(hband, title="Filtered True Range High Band", color=fcolor)
lbandplot = plot(lband, title="Filtered True Range Low Band", color=fcolor)

//Channel Fill
fill(hbandplot, lbandplot, title="Channel Fill", color=fcolor, transp=80)

//Bar Color
barcolor(barcolor)


longCondition = crossover(close, hband) and timeCondition
closeAllCondition = crossunder(close, hband) and timeCondition

if longCondition
    strategy.entry("long", strategy.long)

if closeAllCondition
    strategy.close("long")

Mehr