Handelsstrategie mit gleitendem Durchschnitt und gewichteter Standardabweichung


Erstellungsdatum: 2023-11-24 13:54:58 zuletzt geändert: 2023-11-24 13:54:58
Kopie: 0 Klicks: 773
1
konzentrieren Sie sich auf
1617
Anhänger

Handelsstrategie mit gleitendem Durchschnitt und gewichteter Standardabweichung

Überblick

Die Strategie verwendet den gewichteten Standard Differenz-Indikator in Kombination mit einem Moving Average, um Trend-Handel mit Kryptowährungen zu realisieren. Die Strategie berechnet den gewogenen Standard Differenz-Kanal des Preises anhand des Schlusskurses und der Transaktionsmenge in einem bestimmten Zeitraum.

Strategieprinzip

Der Code definiert zwei benutzerdefinierte Funktionen, die jeweils abweichend von der gewichteten Standarddifferenz für die Berechnung von Zeitreihen und Arrays berechnet werden. Die wichtigsten Schritte sind:

  1. Berechnung eines gewogenen Durchschnittspreises nach Schlusskurs und Transaktionsvolumen
  2. Berechnung des Quadrats der Abweichung von der Durchschnittswerte für jede K-Linie
  3. Die Differenz wird berechnet anhand des durchschnittlichen Wertes, bereinigt um die Probenmenge und das Gewicht.
  4. Der Quadrat hat eine Standarddifferenz.

Auf diese Weise erhalten wir einen Kanal mit einer gewogenen Durchschnittspreis in der Mitte und einer Standarddifferenz in der Unterseite. Wenn der Preis von unten den unteren Teil des Kanals durchbricht, machen wir mehr; wenn er von oben den oberen Teil des Kanals durchbricht, machen wir weniger.

Analyse der Stärken

Der größte Vorteil dieser Strategie besteht darin, dass sie eine Kombination aus Moving Average und Volatilitätsanalyse darstellt. Die Moving Average beurteilt die Richtung der Markttrends, die Standarddifferenz definiert einen angemessenen Bereich, die sich gegenseitig verifizieren und eine hohe Zuverlässigkeit aufweisen. Darüber hinaus kann das Transaktionsgewicht falsche Durchbrüche filtern und die Wahrscheinlichkeit eines tatsächlichen Durchbruchs ist höher.

Die Strategie bietet auch einen Stop-Loss-Stop, um den Trend zu erfassen und zu vermeiden, dass ein Umkippen zu einem übermäßigen Verlust führt. Dies ist ein Punkt, den viele Anfänger nicht beherrschen können.

Risikoanalyse

Das Risiko besteht hauptsächlich darin, dass die Märkte stark schwanken können. In diesem Fall schwanken auch die Standardabweichungskanäle erheblich und sind für die Beurteilung nicht geeignet. Darüber hinaus ist die Fehlerrate hoch, wenn die Auswahlperiode zu kurz ist und leicht durch Lärm gestört wird.

Die Gegenmaßnahme ist, dass die Periodiparameter angepasst werden können, um die Kurve zu glätten. Es kann auch in Kombination mit anderen Indikatoren wie dem RSI in Betracht gezogen werden, um die Bestätigung des Durchbruchs zu erhöhen.

Optimierungsrichtung

  1. Optimierung der Zyklusparameter. Verschiedene Zyklen wie 5 Minuten, 15 Minuten, 30 Minuten können getestet werden, um die optimale Kombination zu finden
  2. Optimierung der Stop-Loss-Stop-Ratio. Verschiedene Stop-Loss-Stop-Punkte testen, um eine optimale Rendite zu erzielen
  3. Erhöhte Filterbedingungen, z. B. kombinierter Verkehr, um falsche Durchbrüche zu vermeiden, die einen Verlust verursachen
  4. Erhöhung der Anzeige-Werte, um die Fehlerrate zu verringern, z. B. durch die Bestätigung von K-Linien-Einheiten, wie z. B. die Position des Schließpreises, die Länge der Schattenlinie

Zusammenfassen

Die Strategie nutzt erfolgreich den gewichteten Standard-Differenz-Indikator, unterstützt durch die Beurteilung der Richtung durch bewegliche Durchschnitte, um die Trends für Kryptowährungen zu verfolgen. Gleichzeitig hilft eine vernünftige Stop-Loss-Einstellung, die Marktdynamik zu erfassen und zu verhindern, dass eine übermäßige Umkehr zu Verlusten führt. Durch die Parameteranpassung und Multi-Indikator-Verifizierung kann die Strategie weiter optimiert und eine zuverlässige quantitative Handelsstrategie gebildet werden.

Strategiequellcode
/*backtest
start: 2023-11-16 00:00:00
end: 2023-11-23 00:00:00
period: 45m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © rumpypumpydumpy   © cache_that_pass

//@version=4
strategy("[cache_that_pass] 1m 15m Function - Weighted Standard Deviation", overlay=true, pyramiding=0, default_qty_type=strategy.percent_of_equity, default_qty_value=20, initial_capital=10000, commission_type=strategy.commission.percent, commission_value=0.075)

f_weighted_sd_from_series(_src, _weight, _n) => //{
//  @function: Calculates weighted mean, variance, standard deviation, MSE and RMSE from time series variables
//  @parameters:
//      _src: time series variable of sample values
//      _weight: time series of corresponding weight values.
//      _n : number of samples
    _xw = _src * _weight
    _sum_weight = sum(_weight, _n)
    _mean = sum(_xw, _n) / _sum_weight
    float _sqerror_sum = 0
    int _nonzero_n = 0
    for _i = 0 to _n - 1
        _sqerror_sum := _sqerror_sum + pow(_mean - _src[_i], 2) * _weight[_i]
        _nonzero_n := _weight[_i] != 0 ? _nonzero_n + 1 : _nonzero_n
    _variance = _sqerror_sum / ((_nonzero_n - 1) * _sum_weight / _nonzero_n)
    _dev = sqrt(_variance)
    _mse = _sqerror_sum / _sum_weight
    _rmse = sqrt(_mse)
    [_mean, _variance, _dev, _mse, _rmse]
//}
// -----------------------------------------------------------------------------

f_weighted_sd_from_arrays(_a_src, _a_weight, _n) => //{
//  @function: Calculates weighted mean, variance, standard deviation, MSE and RMSE from arrays
//  Expects index 0 of the arrays to be the most recent sample and weight values!
//  @parameters:
//      _a_src: array of sample values
//      _a_weight: array of corresponding weight values.
//      _n : number of samples
    float _mean = na, float _variance = na, float _dev = na, float _mse = na
    float _rmse = na, float _sqerror_sum = na, float _sum_weight = na
    float[] _a_xw = array.new_float(_n)
    int _nonzero_n = 0
    if array.size(_a_src) >= _n
        _sum_weight := 0
        _sqerror_sum := 0
        for _i = 0 to _n - 1
            array.set(_a_xw, _i, array.get(_a_src, _i) * array.get(_a_weight, _i))
            _sum_weight := _sum_weight + array.get(_a_weight, _i)
            _nonzero_n := array.get(_a_weight, _i) != 0 ? _nonzero_n + 1 : _nonzero_n
        _mean := array.sum(_a_xw) / _sum_weight
        for _j = 0 to _n - 1
            _sqerror_sum := _sqerror_sum + pow(_mean - array.get(_a_src, _j), 2) * array.get(_a_weight, _j)
        _variance := _sqerror_sum / ((_nonzero_n - 1) * _sum_weight / _nonzero_n)
        _dev := sqrt(_variance)
        _mse := _sqerror_sum / _sum_weight
        _rmse := sqrt(_mse)
    [_mean, _variance, _dev, _mse, _rmse]
//}


// -----------------------------------------------------------------------------
// Example usage : 
// -----------------------------------------------------------------------------

len = input(20)

// -----------------------------------------------------------------------------
// From series :
// -----------------------------------------------------------------------------
[m, v, d, mse, rmse] = f_weighted_sd_from_series(close, volume, len)


plot(m, color = color.blue)
plot(m + d * 2, color = color.blue)
plot(m - d * 2, color = color.blue)
// -----------------------------------------------------------------------------



// -----------------------------------------------------------------------------
// From arrays : 
// -----------------------------------------------------------------------------
var float[] a_src = array.new_float()
var float[] a_weight = array.new_float()

if barstate.isfirst
    for i = 1 to len
        array.unshift(a_weight, i)

array.unshift(a_src, close)

if array.size(a_src) > len
    array.pop(a_src)

[a_m, a_v, a_d, a_mse, a_rmse] = f_weighted_sd_from_arrays(a_src, a_weight, len)

plot(a_m, color = color.orange)
plot(a_m + a_d * 2, color = color.orange)
plot(a_m - a_d * 2, color = color.orange)
// -----------------------------------------------------------------------------


series_text = "Mean : " + tostring(m) + "\nVariance : " + tostring(v) + "\nSD : " + tostring(d) + "\nMSE : " + tostring(mse) +  "\nRMSE : " + tostring(rmse)
array_text = "Mean : " + tostring(a_m) + "\nVariance : " + tostring(a_v) + "\nSD : " + tostring(a_d) + "\nMSE : " + tostring(a_mse) +  "\nRMSE : " + tostring(a_rmse)
debug_text = "Volume weighted from time series : \n" + series_text + "\n\nLinearly weighted from arrays : \n" + array_text

//debug = label.new(x = bar_index, y = close, text = debug_text, style = label.style_label_left)
//.delete(debug[1])

//test strategy
if low <= (m - d * 2)
    strategy.entry("LE", strategy.long)
if high >= (m + d * 2)
    strategy.entry("SE", strategy.short)

// User Options to Change Inputs (%)
stopPer = input(3.11, title='Stop Loss %', type=input.float) / 100
takePer = input(7.50, title='Take Profit %', type=input.float) / 100

// Determine where you've entered and in what direction
longStop = strategy.position_avg_price * (1 - stopPer)
shortStop = strategy.position_avg_price * (1 + stopPer)
shortTake = strategy.position_avg_price * (1 - takePer)
longTake = strategy.position_avg_price * (1 + takePer)

if strategy.position_size > 0 
    strategy.exit(id="Close Long", stop=longStop, limit=longTake)
//    strategy.close("LE", when = (longStop) or (longTake), qty_percent = 100)
if strategy.position_size < 0 
    strategy.exit(id="Close Short", stop=shortStop, limit=shortTake)
//    strategy.close("SE", when = (shortStop) or (shortTake), qty_percent = 100)