양적 거래에서 K 라인 데이터 처리

저자:선함, 2019-09-03 11:15:30, 업데이트: 2023-11-07 20:43:41

img

K 라인은 양적 거래에서 어떻게 데이터를 처리합니까?

양적 거래 전략을 작성할 때, K-라인 데이터를 사용하여, 비표준 주기 K-라인 데이터가 필요한 경우가 종종 있습니다. 예를 들어, 12분 주기 K-라인 데이터와 4시간 K-라인 사이클 데이터가 필요합니다. 일반적으로 이러한 비표준 주기는 직접 사용할 수 없습니다. 그렇다면 그러한 요구를 어떻게 처리합니까?

비표준주기 K 라인 데이터는 작은 주기의 데이터를 결합하여 얻을 수 있다. 이를 그림으로, 여러 주기의 가장 높은 가격은 여러 주기 K 라인 합성 후 가장 높은 가격으로 계산되고, 가장 낮은 가격은 합성 후 가장 낮은 가격으로 계산되며, 오픈 가격은 변하지 않는다. K-라인의 원자재 데이터의 첫 번째 오픈 가격은 합성된다. 종료 가격은 K-라인의 마지막 원자재 데이터의 종료 가격과 일치한다. 시간은 오픈 가격 k 라인의 시간을 사용합니다. 거래 부피는 합산 및 계산된 원자재 데이터를 사용합니다.

그림과 같이:

  • 생각

예를 들어 블록체인 자산 BTC_USDT를 1시간을 4시간으로 합성해 봅시다.

img img img img

시간 가장 높은 오픈 가장 낮은 닫아
2019.8.12 00:00 11447.07 11382.57 11367.2 11406.92
2019.8.12 01:00 11420 11405.65 11366.6 11373.83
2019.8.12 02:00 11419.24 11374.68 11365.51 11398.19
2019.8.12 03:00 11407.88 11398.59 11369.7 11384.71

4개의 1시간 사이클의 데이터는 하나의 4시간 사이클 데이터로 결합됩니다.

개시 가격은 00:00 시간 첫 번째 K 라인 개시 가격입니다: 11382.57 종료 가격은 마지막 k 라인 종료 가격입니다 03:00: 11384.71 가장 높은 가격은 그 중 가장 높은 가격을 찾는 것입니다: 11447.07 가장 낮은 가격은 그 중 가장 낮은 가격을 찾는 것입니다: 11365.51

참고: 중국 재화 선물 시장은 정상적인 거래일에 오후 3시에 폐쇄됩니다.

4시간 사이클 시작 시간은 첫 1시간 K 라인의 시작 시간, 즉 2019.8.12 00:00

이 4시간 k 라인의 부피로 1시간 k 라인의 부피의 합이 사용됩니다.

4시간 K 라인이 합성됩니다.

High: 11447.07
Open: 11382.57
Low: 11365.51
Close: 11384.71
Time: 209.8.12 00:00

img

데이터의 일관성을 볼 수 있습니다.

  • 코드 실행

초기 아이디어를 이해한 후, 요구사항을 실현하기 위해 코드를 수동으로 작성할 수 있습니다.

이 코드는 참조용으로만 사용됩니다.

function GetNewCycleRecords (sourceRecords, targetCycle) { // K line synthesis function
      var ret = []
      
      // First get the source K line data cycle
      if (!sourceRecords || sourceRecords.length < 2) {
          Return null
      }
      var sourceLen = sourceRecords.length
      var sourceCycle = sourceRecords[sourceLen - 1].Time - sourceRecords[sourceLen - 2].Time

      if (targetCycle % sourceCycle != 0) {
          Log("targetCycle:", targetCycle)
          Log("sourceCycle:", sourceCycle)
          throw "targetCycle is not an integral multiple of sourceCycle."
      }

      if ((1000 * 60 * 60) % targetCycle != 0 && (1000 * 60 * 60 * 24) % targetCycle != 0) {
          Log("targetCycle:", targetCycle)
          Log("sourceCycle:", sourceCycle)
          Log((1000 * 60 * 60) % targetCycle, (1000 * 60 * 60 * 24) % targetCycle)
          throw "targetCycle cannot complete the cycle."
      }

      var multiple = targetCycle / sourceCycle


      var isBegin = false
      var count = 0
      var high = 0
      var low = 0
      var open = 0
      var close = 0
      var time = 0
      var vol = 0
      for (var i = 0 ; i < sourceLen ; i++) {
          // Get the time zone offset value
          var d = new Date()
          var n = d.getTimezoneOffset()

          if ((1000 * 60 * 60 * 24) - sourceRecords[i].Time % (1000 * 60 * 60 * 24) + (n * 1000 * 60)) % targetCycle == 0) {
              isBegin = true
          }

          if (isBegin) {
              if (count == 0) {
                  High = sourceRecords[i].High
                  Low = sourceRecords[i].Low
                  Open = sourceRecords[i].Open
                  Close = sourceRecords[i].Close
                  Time = sourceRecords[i].Time
                  Vol = sourceRecords[i].Volume

                  count++
              } else if (count < multiple) {
                  High = Math.max(high, sourceRecords[i].High)
                  Low = Math.min(low, sourceRecords[i].Low)
                  Close = sourceRecords[i].Close
                  Vol += sourceRecords[i].Volume

                  count++
              }

              if (count == multiple || i == sourceLen - 1) {
                  Ret.push({
                      High : high,
                      Low : low,
                      Open : open,
                      Close : close,
                      Time : time,
                      Volume : vol,
                  })
                  count = 0
              }
          }
      }

      Return ret
  }

  // test
  function main () {
      while (true) {
          var r = exchange.GetRecords() // Raw data, as the basic K-line data of the synthesize K line. for example, to synthesize a 4-hour K-line, you can use the 1-hour K-line as the raw data.
          var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4) // Pass the original K-line data r through the GetNewCycleRecords function, and the target cycles, 1000 * 60 * 60 * 4, ie the target synthesis cycle is 4 hours K-line data .

          $.PlotRecords(r2, "r2") // The strategy class library bar can be selected by check the line class library, and calling the $.PlotRecords line drawing class library to export the function drawing.
          Sleep(1000) // Each cycle is separated by 1000 milliseconds, preventing access to the K-line interface too much, resulting in transaction restrictions.
      }
  }

사실, K선을 합성하려면 두 가지가 필요합니다. 첫째는 원료 데이터입니다. 즉, 더 작은 사이클의 K-라인 데이터입니다.var r = exchange.GetRecords()더 작은 사이클 K 선 데이터를 얻기 위해서입니다.

두번째는 합성주기의 크기를 알아내는 것입니다. 이를 위해 GetNewCycleRecords 함수 알고리즘을 사용합니다.

다음 사항에 유의하시기 바랍니다.

  1. 목표 주기는 GetNewCycleRecords 함수에서 데이터를 위한 원료로 통과한 K 직선의 주기와 작을 수 없습니다. 왜냐하면 더 작은 주기의 데이터를 더 큰 주기로 합성할 수 없기 때문입니다. 단지 그 반대입니다.

  2. 목표 주기는 cycle closed로 설정되어야 합니다. cycle closed은 무엇입니까? 간단히 말해서, 한 시간 또는 하루 이내에 목표 주기의 시간 범위가 결합되어 폐쇄 된 루프를 형성합니다.

예를 들어:

12분 사이클의 K-라인은 0:0부터 매 시간마다 시작되며, 첫 번째 사이클은 00:00:00 ~ 00:12:00, 두 번째 사이클은 00:12: 00 ~ 00: 24:00, 세 번째 사이클은 00:24: 00 ~ 00:36:00, 네 번째 사이클은 00:36:00 ~ 00:48:00, 다섯 번째 사이클은 00:48 :00 ~ 01:00:00입니다.

13분 사이클이라면 닫히지 않은 사이클입니다. 이 사이클에 의해 계산된 데이터는 고유하지 않습니다. 왜냐하면 합성된 데이터는 합성된 데이터의 시작점에 따라 다르기 때문입니다.

실제 시장에서 실행:

img

콘트라스트 교환 차트

img

  • K-라인 데이터를 사용하여 필요한 데이터 구조를 구축

모든 K 직선의 가장 높은 가격의 이동 평균을 계산하고 싶습니다. 어떻게 해야 할까요?

보통 우리는 닫기 가격의 평균을 사용하여 이동 평균을 계산하지만 때로는 가장 높은 가격, 가장 낮은 가격, 개시 가격을 사용하는 수요가 있습니다.

이러한 추가 요구에 대해, 교환.GetRecords ()) 함수가 반환하는 K 직선 데이터는 직접 지표 계산 함수로 전달할 수 없습니다.

예를 들어: 이talib.MA이동 평균 지표 계산 함수는 두 개의 매개 변수를 가지고 있는데, 첫 번째 매개 변수는 입력해야 하는 데이터이고, 두 번째 매개 변수는 지표 사이클이다.

예를 들어, 우리는 아래와 같이 지표를 계산해야 합니다.

img

K선 주기는 4시간입니다.

거래 시장 코팅 차트에서는 9의 사이클 매개 변수와 평균 라인을 설정했습니다.

계산된 데이터 소스는 바당 가장 높은 가격을 사용합니다.

img

즉, 이 이동 평균선은 9개의 4시간 주기의 K-라인 바의 가장 높은 평균 가격의 평균으로 구성됩니다.

교환 데이터와 같은지 확인하기 위해 데이터 자체를 만들어 봅시다.

var highs = []
for (var i = 0 ; i < r2.length ; i++) {
    highs.push(r2[i].High)
}

이동 평균 지표의 값을 얻기 위해 각 바의 가장 높은 가격을 계산해야 하기 때문에, 우리는 각 바에 대한 가장 높은 가격을 가진 각 데이터 요소가 있는 배열을 구성해야 합니다.

보시다시피,highs변수는 처음에는 빈 배열이고, 우리는 r2 k-선 데이터 변수를 통과합니다 (r2를 기억하지 않습니까? 위의 4시간 K-선을 합성하는 주 함수의 코드를 보세요.)

r2의 각 바의 가장 높은 가격을 읽으십시오 (즉 r2[i].High, i는 0에서 r2까지의 범위입니다.length - 1), 그리고 입력highs이 방법으로 우리는 K-라인 데이터 바와 1대1 대응하는 데이터 구조를 구축합니다.

이 순간,highs통과 할 수 있습니다talib.MA이동 평균을 계산하는 함수입니다.

완전한 예제:

function main () {
     while (true) {
         var r = exchange.GetRecords()
         var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4)
         if (!r2) {
             Continue
         }
        
         $.PlotRecords(r2, "r2") // Draw the K line
        
         var highs = []
         for (var i = 0 ; i < r2.length ; i++) {
             Highs.push(r2[i].High)
         }
        
         var ma = talib.MA(highs, 9) // use the moving average function "talib.MA" to calculate the moving average indicator
         $.PlotLine("high_MA9", ma[ma.length - 2], r2[r2.length - 2].Time) // Use the line drawing library to draw the moving average indicator on the chart
        
         Sleep(1000)
     }
}

백테스트:

img

그림에서 마우스 포인트 위치의 평균 지표 값은 11466.9289입니다 볼 수 있습니다

위의 코드는 테스트를 실행하는 전략에 복사 할 수 있습니다, Draw Line Library을 확인하고 저장하는 것을 기억하십시오!

  • 암호화폐 시장에 대한 K-라인 데이터 획득 방법

FMZ Quant 플랫폼은 이미 패키지 인터페이스가 있습니다.exchange.GetRecordsK선 데이터를 얻기 위한 기능입니다.

다음은 데이터를 얻기 위해 교환의 K-라인 데이터 인터페이스에 대한 직접 접근에 초점을 맞추고, 때로는 더 많은 K 라인을 얻기 위해 매개 변수를 지정해야 하기 때문에, 패키지GetRecords인터페이스는 일반적으로 100K줄을 반환합니다. 초기에는 100K줄이 필요하다는 전략에 직면하면 수집 프로세스를 기다려야 합니다.

가능한 한 빨리 전략을 실행시키기 위해 함수를 캡슐화하고, 거래소의 K 라인 인터페이스에 직접 액세스하고, 더 많은 K 라인 데이터를 얻기 위해 매개 변수를 지정할 수 있습니다.

예를 들어 Huobi 거래소에서 BTC_USDT 거래 쌍을 사용하여 다음 요구 사항을 구현합니다.

교환의 API 문서를 찾아 K-line 인터페이스 설명을 참조하십시오:

img

https://huobiapi.github.io/docs/spot/v1/en/#get-klines-candles

매개 변수

이름 종류 꼭 필요한가요? 설명 가치
기호 문자열 사실 거래 쌍 , ,
기간 문자열 사실 각 k 행의 시간 간격인 데이터의 시간 곡선을 반환합니다. 1분, 5분, 15분, 30분, 60분, 1일, 1개월, 1주, 1년
크기 정수 거짓 데이터 K 줄의 수를 반환합니다. [1, 2000]

테스트 코드:

function GetRecords_Huobi (period, size, symbol) {
    var url = "https://api.huobi.pro/market/history/kline?" + "period=" + period + "&size=" + size + "&symbol=" + symbol
    var ret = HttpQuery(url)
    
    try {
        var jsonData = JSON.parse(ret)
        var records = []
        for (var i = jsonData.data.length - 1; i >= 0 ; i--) {
            records.push({
                Time : jsonData.data[i].id * 1000,
                High : jsonData.data[i].high,
                Open : jsonData.data[i].open,
                Low : jsonData.data[i].low,
                Close : jsonData.data[i].close,
                Volume : jsonData.data[i].vol,
            })
        }
        return records
    } catch (e) {
        Log(e)
    }
}  


function main() {
    var records = GetRecords_Huobi("1day", "300", "btcusdt")
    Log(records.length)
    $.PlotRecords(records, "K")
}

img img

로그에서 볼 수 있습니다, 인쇄records.length300입니다.recordsK선 데이터 바는 300입니다.img


관련

더 많은