
Strategi ini adalah strategi perdagangan kuantitatif eksperimen yang menggabungkan indikator purata bergerak dan algoritma kNN pembelajaran mesin untuk menghasilkan isyarat perdagangan. Strategi ini menggunakan persilangan garis rata-rata VWMA dari dua tempoh yang berbeza untuk menentukan arah trend, dan menggabungkan kedua-dua indikator MFI dan ADX untuk memfilter isyarat melalui algoritma kNN untuk meningkatkan kebolehpercayaan isyarat.
Penunjuk teras strategi ini adalah garis rata-rata VWMA dengan dua parameter yang berbeza, iaitu garis cepat dan garis perlahan. Apabila garis cepat melintasi garis perlahan, ia menghasilkan isyarat beli, dan apabila garis cepat melintasi garis perlahan, ia menghasilkan isyarat jual. Selain itu, strategi ini memperkenalkan dua penunjuk tambahan, MFI dan ADX, yang menilai kebolehpercayaan isyarat dalam keadaan pasaran semasa melalui algoritma klasifikasi KNN.
Idea algoritma kNN adalah membandingkan data baru dengan data sejarah, menilai hasil yang sesuai dengan data sejarah k yang paling dekat, dan mengklasifikasikan berdasarkan k hasil sejarah dengan cara undi majoriti. Strategi ini menggunakan MFI dan ADX sebagai dua parameter input algoritma kNN untuk menilai pergerakan harga sejarah ketika kedua-dua indikator ini digabungkan (naik atau turun), yang memfilterkan isyarat semasa, meningkatkan kualiti isyarat.
Tindakan pencegahan:
Strategi ini masih mempunyai ruang untuk pengoptimuman yang besar:
Dengan memperkenalkan lebih banyak penunjuk dan algoritma pembelajaran mesin, ia dijangka dapat meningkatkan lagi kestabilan dan kadar pulangan strategi.
Strategi ini adalah strategi perdagangan kuantitatif percubaan berdasarkan penunjuk garis rata-rata VWMA dan algoritma pembelajaran mesin KNN. Ia mempunyai keupayaan trend yang kuat, dan ciri-ciri penapisan isyarat melalui pembelajaran mesin. Ruang strategi ini luas, dan diharapkan dapat menghasilkan kesan yang lebih baik dengan memperkenalkan lebih banyak ciri dan algoritma pengoptimuman.
/*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)