Esta es una estrategia comercial experimental cuantitativa

El autor:¿ Qué pasa?, Fecha: 2023-12-22 14:13:27
Las etiquetas:

img

Resumen general

Esta es una estrategia de trading cuantitativa experimental que combina indicadores de promedio móvil y algoritmos de aprendizaje automático kNN para generar señales de trading.

Principios de estrategia

Los indicadores centrales de esta estrategia son dos líneas VWMA con parámetros diferentes, a saber, línea rápida y línea lenta. Cuando la línea rápida cruza por encima de la línea lenta, se genera una señal de compra. Cuando la línea rápida cruza por debajo de la línea lenta, se genera una señal de venta. Además, esta estrategia introduce dos indicadores auxiliares, MFI y ADX, para juzgar la confiabilidad de la señal actual bajo las condiciones actuales del mercado a través del algoritmo de clasificación kNN.

La idea detrás del algoritmo kNN es comparar los nuevos datos con los datos históricos para determinar los resultados correspondientes a los k datos históricos más similares, y clasificar en función del voto mayoritario de estos k resultados históricos.

Ventajas

  • Utilice la capacidad de seguimiento de tendencias de VWMA y genere señales comerciales a través de cruces de promedios móviles
  • Aplicar indicadores de IFM y ADX para la extracción de características multidimensionales para ayudar a determinar la dirección de la tendencia
  • Aprovechar el algoritmo de aprendizaje automático kNN para optimizar y filtrar dinámicamente las señales comerciales
  • Estrategia experimental con mucho margen de mejora mediante una mayor verificación y optimización de los datos

Riesgos y mitigaciones

  • Las líneas VWMA tienden a retrasarse
  • Las IFM y las ADX tienen un cierto retraso, lo que puede inducir a juzgar erróneamente las condiciones del mercado
  • Los parámetros del algoritmo kNN (por ejemplo, valor k) pueden tener un impacto significativo en los resultados
  • La estrategia experimental puede tener un rendimiento inferior en el comercio en vivo

Mitigantes:

  • Ajustar los parámetros de MA para reducir el retraso
  • Mejorar los indicadores para evaluar con mayor precisión las tendencias
  • Optimizar los parámetros de kNN para mejorar la aptitud
  • Verificar la estrategia a través de pruebas de retroceso y comercio en papel

Direcciones de optimización

Hay mucho espacio para optimizar esta estrategia:

  • Añadir más indicadores MA para construir combinaciones MA
  • Pruebe diferentes indicadores auxiliares como el MACD, KDJ, etc.
  • Mejorar el algoritmo kNN, por ejemplo, utilizando diferentes métricas de distancia
  • Prueba otros algoritmos de aprendizaje automático como SVM, Random Forest etc.
  • Ajuste de parámetros para encontrar conjuntos óptimos de parámetros

La introducción de más indicadores y algoritmos de aprendizaje automático puede mejorar aún más la estabilidad y la rentabilidad de la estrategia.

Resumen de las actividades

Esta es una estrategia comercial cuantitativa experimental basada en indicadores VWMA y algoritmos de aprendizaje automático kNN. Tiene la ventaja de una fuerte capacidad de seguimiento de tendencias mientras filtra señales a través del aprendizaje automático. La estrategia tiene un gran margen de expansión al introducir más características y algoritmos de optimización para mejores resultados.


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

Más.