리소스 로딩... 로딩...

이것은 실험적인 양적 거래 전략입니다.

저자:차오장, 날짜: 2023-12-22 14:13:27
태그:

This is an experimental quantitative trading strategy

전반적인 설명

이것은 이동 평균 지표와 kNN 기계 학습 알고리즘을 결합하여 거래 신호를 생성하는 실험적 양적 거래 전략이다. 트렌드 방향을 결정하기 위해 서로 다른 기간의 두 VWMA 라인의 크로스오버를 사용하고, 신호의 신뢰성을 향상시키기 위해 kNN 알고리즘을 통해 신호를 필터링하기 위해 MFI 및 ADX 지표를 사용합니다.

전략 원칙

이 전략의 핵심 지표는 두 가지 다른 매개 변수인 빠른 라인과 느린 라인을 가진 두 개의 VWMA 라인이다. 빠른 라인이 느린 라인의 위를 넘을 때 구매 신호가 생성된다. 빠른 라인이 느린 라인의 아래를 넘을 때 판매 신호가 생성된다. 또한 이 전략은 현재 시장 조건 하에서 현재 신호의 신뢰성을 kNN 분류 알고리즘을 통해 판단하기 위해 두 가지 보조 지표인 MFI와 ADX를 도입한다.

kNN 알고리즘의 아이디어는 새로운 데이터를 역사적 데이터와 비교하여 가장 유사한 역사적 데이터 k에 해당하는 결과를 결정하고 이러한 k 역사적 결과의 대다수 투표에 따라 분류하는 것입니다. 이 전략은 MFI와 ADX를 kNN 알고리즘의 두 입력 매개 변수로 사용하여 이러한 지표 조합에 따라 역사적 가격 움직임 (상승 추세 또는 하락 추세) 을 결정하여 현재 신호를 필터링하여 신호 품질을 향상시킵니다.

장점

  • VWMA의 트렌드 추적 능력을 활용하고 이동 평균 크로스오버를 통해 거래 신호를 생성합니다.
  • 트렌드 방향을 결정하는 데 도움이 되는 다차원적 특징 추출을 위해 MFI와 ADX 지표를 적용합니다.
  • kNN 기계 학습 알고리즘을 활용하여 동적으로 거래 신호를 최적화하고 필터링합니다.
  • 더 많은 데이터 검증 및 최적화로 개선 할 수있는 넓은 공간을 가진 실험 전략

위험 및 완화

  • VWMA 라인은 지연하는 경향이 있습니다.
  • MFI와 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)

더 많은