이것은 이동 평균 지표와 kNN 기계 학습 알고리즘을 결합하여 거래 신호를 생성하는 실험적 양적 거래 전략이다. 트렌드 방향을 결정하기 위해 서로 다른 기간의 두 VWMA 라인의 크로스오버를 사용하고, 신호의 신뢰성을 향상시키기 위해 kNN 알고리즘을 통해 신호를 필터링하기 위해 MFI 및 ADX 지표를 사용합니다.
이 전략의 핵심 지표는 두 가지 다른 매개 변수인 빠른 라인과 느린 라인을 가진 두 개의 VWMA 라인이다. 빠른 라인이 느린 라인의 위를 넘을 때 구매 신호가 생성된다. 빠른 라인이 느린 라인의 아래를 넘을 때 판매 신호가 생성된다. 또한 이 전략은 현재 시장 조건 하에서 현재 신호의 신뢰성을 kNN 분류 알고리즘을 통해 판단하기 위해 두 가지 보조 지표인 MFI와 ADX를 도입한다.
kNN 알고리즘의 아이디어는 새로운 데이터를 역사적 데이터와 비교하여 가장 유사한 역사적 데이터 k에 해당하는 결과를 결정하고 이러한 k 역사적 결과의 대다수 투표에 따라 분류하는 것입니다. 이 전략은 MFI와 ADX를 kNN 알고리즘의 두 입력 매개 변수로 사용하여 이러한 지표 조합에 따라 역사적 가격 움직임 (상승 추세 또는 하락 추세) 을 결정하여 현재 신호를 필터링하여 신호 품질을 향상시킵니다.
완화:
이 전략을 최적화할 수 있는 많은 여지가 있습니다.
더 많은 지표와 기계 학습 알고리즘을 도입하면 전략의 안정성과 수익성이 더욱 향상될 수 있습니다.
이 전략은 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)