Chiến lược giao dịch định lượng học máy kNN dựa trên VWMA và MFI/ADX


Ngày tạo: 2023-12-22 14:13:27 sửa đổi lần cuối: 2023-12-22 14:13:27
sao chép: 0 Số nhấp chuột: 762
1
tập trung vào
1623
Người theo dõi

Chiến lược giao dịch định lượng học máy kNN dựa trên VWMA và MFI/ADX

Tổng quan

Chiến lược này là một chiến lược giao dịch định lượng thực nghiệm, kết hợp các chỉ số trung bình di chuyển và thuật toán kNN của máy học để tạo ra tín hiệu giao dịch. Chiến lược này sử dụng giao thoa của các đường trung bình VWMA của hai chu kỳ khác nhau để xác định hướng xu hướng và kết hợp hai chỉ số MFI và ADX để lọc tín hiệu thông qua thuật toán kNN để tăng độ tin cậy tín hiệu.

Nguyên tắc chiến lược

Chỉ số cốt lõi của chiến lược này là đường trung bình VWMA với hai tham số khác nhau, đường nhanh và đường chậm. Một tín hiệu mua được tạo ra khi đường nhanh đi qua đường chậm và một tín hiệu bán khi đường nhanh đi qua đường chậm. Ngoài ra, chiến lược này đã giới thiệu hai chỉ số phụ trợ MFI và ADX để đánh giá độ tin cậy của tín hiệu trong điều kiện thị trường hiện tại thông qua thuật toán phân loại KNN.

Ý tưởng của thuật toán kNN là so sánh dữ liệu mới với dữ liệu lịch sử, đánh giá kết quả tương ứng với dữ liệu lịch sử k gần nhất, và phân loại theo cách bỏ phiếu đa số dựa trên kết quả lịch sử k này. Chiến lược này sử dụng MFI và ADX làm hai tham số đầu vào của thuật toán kNN để đánh giá xu hướng giá lịch sử khi kết hợp hai chỉ số này (lên hoặc xuống) để lọc tín hiệu hiện tại và cải thiện chất lượng tín hiệu.

Lợi thế chiến lược

  • Sử dụng khả năng theo dõi xu hướng của VWMA để tạo ra điểm mua và bán cùng với đường giao thoa
  • Sử dụng chỉ số MFI và ADX để trích xuất tính năng đa chiều, hỗ trợ định hướng xu hướng
  • Các tín hiệu giao dịch được tối ưu hóa và lọc động bằng thuật toán học máy của kNN
  • Chiến lược thử nghiệm, không gian phát triển lớn, cần được xác minh và tối ưu hóa thông qua nhiều dữ liệu hơn

Rủi ro và biện pháp đối phó

  • VWMA trung bình có thể gây ra sự chậm trễ
  • MFI và ADX có một chút chậm trễ và có thể hiểu sai tình hình thị trường
  • Việc đặt các tham số của thuật toán kNN (ví dụ như chọn giá trị k) có thể ảnh hưởng lớn đến kết quả
  • Các chiến lược thử nghiệm có thể không hoạt động tốt trong thực tế

Phản ứng:

  • Điều chỉnh tham số đường trung bình để giảm độ chậm trễ
  • Cải thiện các thuật toán chỉ số để đánh giá chính xác các xu hướng
  • Tối ưu hóa các tham số của thuật toán kNN để cải thiện hiệu quả phù hợp
  • Sử dụng phản hồi và mô phỏng thực để xác minh chiến lược

Hướng tối ưu hóa

Chiến lược này có thể được tối ưu hóa rất nhiều:

  • Thêm nhiều chỉ số đường trung bình, xây dựng danh mục đường trung bình
  • Thử các chỉ số phụ khác nhau như MACD, KDJ, v.v.
  • Cải thiện thuật toán kNN, chẳng hạn như sử dụng phương pháp đo khoảng cách khác nhau
  • Thử các thuật toán học máy khác như SVM, rừng ngẫu nhiên, v.v.
  • Tối ưu hóa tham số, tìm kiếm sự kết hợp tham số tốt nhất

Các nhà nghiên cứu cho rằng việc đưa ra nhiều chỉ số hơn và các thuật toán học máy có thể làm tăng thêm sự ổn định và lợi nhuận của các chiến lược.

Tóm tắt

Chiến lược này là một chiến lược giao dịch định lượng thực nghiệm dựa trên chỉ số đường trung bình VWMA và thuật toán học máy của KNN. Nó có khả năng theo dõi xu hướng mạnh mẽ, đồng thời có khả năng lọc tín hiệu thông qua học máy.

Mã nguồn chiến lược
/*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)