Это экспериментальная количественная торговая стратегия.

Автор:Чао Чжан, Дата: 2023-12-22 14:13:27
Тэги:

img

Обзор

Это экспериментальная количественная стратегия торговли, которая сочетает в себе индикаторы скользящей средней и алгоритмы машинного обучения kNN для генерации торговых сигналов.

Принципы стратегии

Основными показателями этой стратегии являются две линии VWMA с различными параметрами, а именно быстрая линия и медленная линия. Когда быстрая линия пересекает поверх медленной линии, генерируется сигнал покупки. Когда быстрая линия пересекает ниже медленной линии, генерируется сигнал продажи. Кроме того, эта стратегия вводит два вспомогательных индикатора, MFI и ADX, для оценки надежности текущего сигнала в текущих рыночных условиях через алгоритм классификации kNN.

Идея алгоритма kNN заключается в сравнении новых данных с историческими данными, чтобы определить результаты, соответствующие k наиболее похожим историческим данным, и классифицировать на основе большинства голосов этих k исторических результатов.

Преимущества

  • Использовать возможности VWMA по слежению за трендом и генерировать торговые сигналы с помощью перекресток скользящей средней
  • Применение индикаторов МФИ и ADX для многомерного извлечения признаков, чтобы помочь определить направление тренда
  • Использование алгоритма машинного обучения kNN для динамической оптимизации и фильтрации торговых сигналов
  • Экспериментальная стратегия с большим потенциалом для улучшения за счет проверки и оптимизации данных

Риски и способы их смягчения

  • Линии VWMA, как правило, отстают
  • МФИ и ADX отстают, что может привести к неправильному оценке рыночных условий
  • Параметры алгоритма kNN (например, значение k) могут оказать значительное влияние на результаты
  • Экспериментальная стратегия может быть менее эффективной в режиме реального времени

Уменьшение последствий:

  • Настройка параметров MA для уменьшения задержки
  • Улучшение показателей для более точного оценки тенденций
  • Оптимизировать параметры kNN для улучшения физической подготовки
  • Проверка стратегии с помощью бэкстеста и бумажной торговли

Руководство по оптимизации

Существует большое пространство для оптимизации этой стратегии:

  • Добавить больше показателей MA для построения комбинаций MA
  • Попробуйте различные вспомогательные индикаторы, такие как MACD, KDJ и т.д.
  • Улучшить алгоритм kNN, например, с использованием различных метрик расстояния
  • Попробуйте другие алгоритмы машинного обучения, как SVM, Random Forest и т.д.
  • Настройка параметров для поиска оптимальных наборов параметров

Внедрение большего количества индикаторов и алгоритмов машинного обучения может еще больше улучшить стабильность и рентабельность стратегии.

Резюме

Это экспериментальная количественная торговая стратегия, основанная на индикаторах VWMA и алгоритмах машинного обучения kNN. Она имеет преимущество сильной способности следовать за трендом при фильтрации сигналов с помощью машинного обучения. Стратегия имеет большое пространство для расширения, внедряя больше функций и алгоритмов оптимизации для лучших результатов.


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

Больше