定量取引における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ラインの最後の原材料データの閉じる価格に対応する.時間は開口価格の時間を使用する.取引量は,合計して計算した原材料データを使用する.

図のように:

  • 考える

ブロックチェーンの資産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時間サイクルのデータに結合されます.

オープニング価格は,最初のKラインのオープニング価格で 00:00時: 11382.57 閉じる価格は03:00の最後のkラインの閉じる価格です: 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線を合成するには2つの要素が必要です.第一に,原材料データ,つまり,より小さなサイクルのK線データです.この例では,var r = exchange.GetRecords()小型のサイクルK線データを取得します

これをするためにGetNewCycleRecords関数アルゴリズムを使います. そして,最終的に合成されたK線配列構造のデータを返します.

ご注意ください:

  1. 目標サイクルは,GetNewCycleRecords関数でデータへの原材料として渡したK線のサイクルのより小さくすることはできません. なぜなら,より小さなサイクルのデータをより大きなサイクルで合成することはできません. ただ,その逆です.

  2. 目標サイクルは,サイクル終了に設定する必要があります. サイクル終了とは何か? 簡単に言えば,1時間または1日以内に,目標サイクルの時間帯が結合して閉ループを形成します.

例えば

12分サイクルのK線は0時0分から毎時間開始し,最初のサイクルは00時00分~00時12分,2つのサイクルは00時12分~00時24分,3つのサイクルは00時24分~00時36分,4つのサイクルは00時36分~00時48分,5つのサイクルは00時48分~0時00分です.

13分サイクルの場合,閉まっていないサイクルになります.このようなサイクルの計算によるデータは,合成されたデータの開始点によって異なるため,ユニークではありません.

リアルマーケットで実行します.

img

コントラスト交換図

img

  • K線データを用いて必要なデータ構造を構築する

K線全体で最高価格の移動平均を計算します.

通常,我々は閉店価格の平均を使用して移動平均を計算しますが,時には最高価格,最低価格,開店価格,などを使用する需要があります.

これらの追加要求では,Exchange.GetRecords ((() 機能が返したK行データを直接指標計算機能に転送することはできません.

例えば: についてtalib.MA移動平均指標の計算機能には 2 つのパラメータがあり,最初のパラメータは送信する必要があるデータで,もう1つは指標サイクルのパラメータです.

例えば,下記のように指標を計算する必要があります.

img

K線周期は4時間です

証券市場表では,周期パラメータが9で平均線が設定されています.

計算されたデータソースは,バーあたり最高価格を使用しています.

img

つまり,この移動平均線は9つの4時間のサイクルK線バーの最高平均価格の平均から構成されます.

取引所のデータと同じかどうか調べてみましょう.

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

移動平均指標の値を得るために 各バーの最高価格を計算する必要があるので 各バーの最高価格を持つ各データ要素を配列にする必要があります

グラフが描かれていますhighsr2 k線データ変数を通ります (r2は覚えてないですか? 上記の4時間のK線を合成するメイン関数のコードを見てください)

r2 (すなわち r2[i].High,iは0からr2.長さ-1まで) の各バーの最高価格を読み,その後,押し入りますhighsK線データバーと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ラインを取得するためにパラメータを指定する必要がありますので,パッケージGetRecords初期に100K行以上を必要とする戦略に出くわす場合は,収集プロセスを待たなければなりません.

できるだけ早く戦略を動かすために 関数をカプセル化し 交換所のK線インターフェースに直接アクセスし 参数でより多くのK線データを取得できます

Huobi の取引所での BTC_USDT 取引ペアを例に挙げると,次の要件を実行します.

Exchange の API ドキュメンテーションを見つけ,K-line インターフェースの説明を参照してください.

img

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

パラメータ:

名前 タイプ 必要ですか? 記述 価値
シンボル 文字列 本当 トレーディングペア Btcusdt,ethbtc... ほら ほら
期間 文字列 本当 各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


関連性

もっと