Đây là một chiến lược giao dịch định lượng thử nghiệm.

Tác giả:ChaoZhang, Ngày: 2023-12-22 14:13:27
Tags:

img

Tổng quan

Đây là một chiến lược giao dịch định lượng thử nghiệm kết hợp các chỉ số trung bình động và thuật toán học máy kNN để tạo ra các tín hiệu giao dịch. Nó sử dụng các chéo của hai đường VWMA với các giai đoạn khác nhau để xác định hướng xu hướng và sử dụng các chỉ số MFI và ADX để lọc các tín hiệu thông qua thuật toán kNN để cải thiện độ tin cậy của các tín hiệu.

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

Các chỉ số cốt lõi của chiến lược này là hai đường VWMA với các thông số khác nhau, cụ thể là đường nhanh và đường chậm. Khi đường nhanh vượt qua trên đường chậm, một tín hiệu mua được tạo ra. Khi đường nhanh vượt qua dưới đường chậm, một tín hiệu bán được tạo ra. Ngoài ra, chiến lược này giới thiệu hai chỉ số phụ, MFI và ADX, để đánh giá độ tin cậy của tín hiệu hiện tại 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 đằng sau thuật toán kNN là so sánh dữ liệu mới với dữ liệu lịch sử để xác định kết quả tương ứng với dữ liệu lịch sử tương tự nhất, và phân loại dựa trên đa số phiếu bầu của các kết quả lịch sử này.

Ưu điểm

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

Rủi ro và giảm thiểu

  • Các đường VWMA có xu hướng chậm trễ
  • MFI và ADX có một số sự chậm trễ, có thể đánh giá sai về điều kiện thị trường
  • Các thông số thuật toán kNN (ví dụ giá trị k) có thể có tác động đáng kể đến kết quả
  • Chiến lược thử nghiệm có thể hoạt động kém hơn trong giao dịch trực tiếp

Hạn chế:

  • Điều chỉnh các tham số MA để giảm độ trễ
  • Cải thiện các chỉ số để đánh giá các xu hướng chính xác hơn
  • Tối ưu hóa các thông số kNN để cải thiện thể lực
  • Xác minh chiến lược thông qua backtest và giao dịch giấy

Hướng dẫn tối ưu hóa

Có rất nhiều chỗ để tối ưu hóa chiến lược này:

  • Thêm thêm các chỉ số MA để xây dựng các kết hợp MA
  • Hãy thử các chỉ số hỗ trợ khác nhau như MACD, KDJ vv
  • Cải thiện thuật toán kNN ví dụ như sử dụng các số liệu khoảng cách khác nhau
  • Hãy thử các thuật toán học máy khác như SVM, Random Forest vv
  • Chế độ điều chỉnh tham số để tìm các bộ tham số tối ưu

Việc giới thiệu thêm các chỉ số và thuật toán học máy có thể cải thiện thêm sự ổn định và lợi nhuận của chiến lược.

Tóm lại

Đây là một chiến lược giao dịch định lượng thử nghiệm dựa trên các chỉ số VWMA và thuật toán học máy kNN. Nó có lợi thế của khả năng theo dõi xu hướng mạnh mẽ trong khi lọc tín hiệu thông qua học máy. Chiến lược có nhiều chỗ để mở rộng bằng cách giới thiệu nhiều tính năng và thuật toán tối ưu hóa hơn để có kết quả tốt hơn.


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

Thêm nữa