C' est une stratégie de trading quantitative expérimentale.

Auteur:ChaoZhang est là., Date: 22-12-2023 14:13:27 Je vous en prie.
Les étiquettes:

img

Résumé

Il s'agit d'une stratégie de trading quantitative expérimentale qui combine des indicateurs de moyenne mobile et des algorithmes d'apprentissage automatique kNN pour générer des signaux de trading.

Principes de stratégie

Les indicateurs de base de cette stratégie sont deux lignes VWMA avec des paramètres différents, à savoir la ligne rapide et la ligne lente. Lorsque la ligne rapide traverse au-dessus de la ligne lente, un signal d'achat est généré. Lorsque la ligne rapide traverse au-dessous de la ligne lente, un signal de vente est généré. En outre, cette stratégie introduit deux indicateurs auxiliaires, MFI et ADX, pour juger de la fiabilité du signal actuel dans les conditions actuelles du marché grâce à l'algorithme de classification kNN.

L'idée derrière l'algorithme kNN est de comparer les nouvelles données avec les données historiques pour déterminer les résultats correspondant aux k données historiques les plus similaires, et de catégoriser en fonction du vote majoritaire de ces k résultats historiques.

Les avantages

  • Utiliser les capacités de suivi de tendance de VWMA et générer des signaux de négociation grâce à des croisements de moyennes mobiles
  • Appliquer des indicateurs d'IFM et d'ADX pour l'extraction de caractéristiques multidimensionnelles afin d'aider à déterminer la direction de la tendance
  • Utiliser l'algorithme d'apprentissage automatique kNN pour optimiser et filtrer dynamiquement les signaux de trading
  • Stratégie expérimentale avec une large marge d'amélioration grâce à une plus grande vérification et optimisation des données

Risques et atténuations

  • Les lignes VWMA ont tendance à être en retard
  • Les IFM et les ADX ont un certain retard, ce qui peut induire en erreur les conditions du marché
  • Les paramètres de l'algorithme kNN (par exemple la valeur k) peuvent avoir une incidence significative sur les résultats
  • La stratégie expérimentale peut être moins performante en négociation en direct

Les mesures d'atténuation

  • Régler les paramètres de MA pour réduire le décalage
  • Améliorer les indicateurs pour évaluer plus précisément les tendances
  • Optimiser les paramètres kNN pour améliorer la condition physique
  • Vérifier la stratégie via des backtests et des opérations sur papier

Directions d'optimisation

Il y a beaucoup de marge de manœuvre pour optimiser cette stratégie:

  • Ajouter plus d'indicateurs MA pour construire des combinaisons MA
  • Essayez différents indicateurs auxiliaires comme MACD, KDJ etc.
  • Améliorer l'algorithme kNN, par exemple en utilisant différentes mesures de distance
  • Essayez d'autres algorithmes d'apprentissage automatique comme SVM, Random Forest etc.
  • Ajustement des paramètres pour trouver des ensembles de paramètres optimaux

L'introduction de plus d'indicateurs et d'algorithmes d'apprentissage automatique pourrait encore améliorer la stabilité et la rentabilité de la stratégie.

Résumé

Il s'agit d'une stratégie de trading quantitative expérimentale basée sur des indicateurs VWMA et des algorithmes d'apprentissage automatique kNN. Elle présente l'avantage d'une forte capacité de suivi des tendances tout en filtrant les signaux via l'apprentissage automatique.


/*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)

Plus de