Dies ist eine experimentelle quantitative Handelsstrategie.

Schriftsteller:ChaoZhang, Datum: 22.12.2023 14:13:27
Tags:

img

Übersicht

Dies ist eine experimentelle quantitative Handelsstrategie, die gleitende Durchschnittsindikatoren und kNN-Maschinenlern-Algorithmen kombiniert, um Handelssignale zu generieren.

Strategieprinzipien

Die Kernindikatoren dieser Strategie sind zwei VWMA-Linien mit unterschiedlichen Parametern, nämlich schnelle Linie und langsame Linie. Wenn die schnelle Linie über die langsame Linie geht, wird ein Kaufsignal generiert. Wenn die schnelle Linie unter die langsame Linie geht, wird ein Verkaufssignal generiert. Darüber hinaus führt diese Strategie zwei Hilfsindikatoren ein, MFI und ADX, um die Zuverlässigkeit des aktuellen Signals unter den aktuellen Marktbedingungen durch den kNN-Klassifizierungsalgorithmus zu beurteilen.

Die Idee hinter dem kNN-Algorithmus besteht darin, neue Daten mit historischen Daten zu vergleichen, um die Ergebnisse zu bestimmen, die den k ähnlichsten historischen Daten entsprechen, und basierend auf der Mehrheit der Stimmen dieser k historischen Ergebnisse zu kategorisieren.

Vorteile

  • Nutzen Sie die Trendfolgekapazität von VWMA und generieren Sie Handelssignale durch gleitende Durchschnitts-Crossovers
  • Anwendung von MFI- und ADX-Indikatoren zur mehrdimensionalen Merkmalerfassung zur Bestimmung der Trendrichtung
  • Nutzen Sie den kNN-Maschinenlernalgorithmus zur dynamischen Optimierung und Filterung von Handelssignalen
  • Experimentelle Strategie mit großem Verbesserungsspielraum durch mehr Datenverifizierung und -optimierung

Risiken und Minderungsmaßnahmen

  • VWMA-Linien neigen dazu, zu verzögern
  • MFI und ADX haben eine gewisse Verzögerung, was die Marktbedingungen falsch einschätzen kann
  • Die Parameter des kNN-Algorithmus (z. B. k-Wert) können erhebliche Auswirkungen auf die Ergebnisse haben
  • Experimentelle Strategie kann im Live-Handel unterdurchschnittlich sein

Abmilderung:

  • Anpassung der MA-Parameter zur Verringerung der Verzögerung
  • Verbesserung der Indikatoren zur genaueren Beurteilung der Trends
  • Optimierung der kNN-Parameter zur Verbesserung der Fitness
  • Überprüfung der Strategie durch Backtest und Papierhandel

Optimierungsrichtlinien

Diese Strategie lässt sich weitgehend optimieren:

  • Hinzufügen weiterer MA-Indikatoren zur Konstruktion von MA-Kombinationen
  • Versuchen Sie verschiedene Hilfsindikatoren wie MACD, KDJ etc.
  • Verbessern des kNN-Algorithmus z. B. mit verschiedenen Entfernungsmetriken
  • Versuchen Sie andere maschinelle Lernalgorithmen wie SVM, Random Forest etc.
  • Parameter-Tuning, um optimale Parameter-Sätze zu finden

Die Einführung weiterer Indikatoren und Algorithmen für maschinelles Lernen könnte die Stabilität und Rentabilität der Strategie weiter verbessern.

Zusammenfassung

Dies ist eine experimentelle quantitative Handelsstrategie, die auf VWMA-Indikatoren und kNN-Maschinenlern-Algorithmen basiert. Sie hat den Vorteil, dass sie eine starke Trendverfolgungsfähigkeit bei der Filterung von Signalen über maschinelles Lernen aufweist. Die Strategie bietet viel Raum für die Erweiterung, indem mehr Funktionen und Optimierungsalgorithmen für bessere Ergebnisse eingeführt werden. Als neuartige Strategie gibt es aber auch Risiken, die weitere Verifizierung und Verbesserung erfordern.


/*backtest
start: 2023-11-21 00:00:00
end: 2023-12-21 00:00:00
period: 1h
basePeriod: 15m
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/
// © lastguru

//@version=4
strategy(title="VWMA with kNN Machine Learning: MFI/ADX", shorttitle="VWMA + kNN: MFI/ADX", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)

/////////
// kNN //
/////////

// Define storage arrays for: parameter 1, parameter 2, price, result (up = 1; down = -1)
var knn1 = array.new_float(1, 0)
var knn2 = array.new_float(1, 0)
var knnp = array.new_float(1, 0)
var knnr = array.new_float(1, 0)

// Store the previous trade; buffer the current one until results are in
_knnStore (p1, p2, src) =>
    var prevp1 = 0.0
    var prevp2 = 0.0
    var prevsrc = 0.0
    
    array.push(knn1, prevp1)
    array.push(knn2, prevp2)
    array.push(knnp, prevsrc)
    array.push(knnr, src >= prevsrc ? 1 : -1)
    
    prevp1 := p1
    prevp2 := p2
    prevsrc := src

// Sort two arrays (MUST be of the same size) based on the first.
// In other words, when an element in the first is moved, the element in the second moves as well.
_knnGet(arr1, arr2, k) =>
    sarr = array.copy(arr1)
    array.sort(sarr)
    ss = array.slice(sarr, 0, min(k, array.size(sarr)))
    m = array.max(ss)
    out = array.new_float(0)
    for i = 0 to array.size(arr1) - 1
        if (array.get(arr1, i) <= m)
            array.push(out, array.get(arr2, i))
    out

// Create a distance array from the two given parameters
_knnDistance(p1, p2) =>
    dist = array.new_float(0)
    n = array.size(knn1) - 1
    for i = 0 to n
        d = sqrt( pow(p1 - array.get(knn1, i), 2) + pow(p2 - array.get(knn2, i), 2) )
        array.push(dist, d)
    dist

// Make a prediction, finding k nearest neighbours
_knn(p1, p2, k) =>
    slice = _knnGet(_knnDistance(p1, p2), array.copy(knnr), k)
    knn = array.sum(slice)

////////////
// Inputs //
////////////

SRC = input(title="Source", type=input.source, defval=open)
FAST = input(title="Fast Length", type=input.integer, defval=13)
SLOW = input(title="Slow Length", type=input.integer, defval=19)
FILTER = input(title="Filter Length", type=input.integer, defval=13)
SMOOTH = input(title="Filter Smoothing", type=input.integer, defval=6)
KNN = input(title="kNN nearest neighbors (k)", type=input.integer, defval=23)
BACKGROUND = input(false,title = "Draw background")

////////
// MA //
////////
fastMA = vwma(SRC, FAST)
slowMA = vwma(SRC, SLOW)

/////////
// DMI //
/////////

// Wilder's Smoothing (Running Moving Average)
_rma(src, length) =>
    out = 0.0
    out := ((length - 1) * nz(out[1]) + src) / length

// DMI (Directional Movement Index)
_dmi (len, smooth) =>
    up = change(high)
    down = -change(low)
    plusDM = na(up) ? na : (up > down and up > 0 ? up : 0)
    minusDM = na(down) ? na : (down > up and down > 0 ? down : 0)
    trur = _rma(tr, len)
    plus = fixnan(100 * _rma(plusDM, len) / trur)
    minus = fixnan(100 * _rma(minusDM, len) / trur)
    sum = plus + minus
    adx = 100 * _rma(abs(plus - minus) / (sum == 0 ? 1 : sum), smooth)
    [plus, minus, adx]

[diplus, diminus, adx] = _dmi(FILTER, SMOOTH)

/////////
// MFI //
/////////

// common RSI function
_rsi(upper, lower) =>
    if lower == 0
        100
    if upper == 0
        0
	100.0 - (100.0 / (1.0 + upper / lower))

mfiUp = sum(volume * (change(ohlc4) <= 0 ? 0 : ohlc4), FILTER)
mfiDown = sum(volume * (change(ohlc4) >= 0 ? 0 : ohlc4), FILTER)
mfi = _rsi(mfiUp, mfiDown)

////////////
// Filter //
////////////

longCondition = crossover(fastMA, slowMA)
shortCondition = crossunder(fastMA, slowMA)

if (longCondition or shortCondition)
    _knnStore(adx, mfi, SRC)
filter = _knn(adx, mfi, KNN)

/////////////
// Actions //
/////////////

bgcolor(BACKGROUND ? filter >= 0 ? color.green : color.red : na)
plot(fastMA, color=color.red)
plot(slowMA, color=color.green)

if (longCondition and filter >= 0)
    strategy.entry("Long", strategy.long)
if (shortCondition and filter < 0)
    strategy.entry("Short", strategy.short)

Mehr