定量的な取引戦略を書いているとき,K線データを使用すると,通常,非標準サイクルのK線データが必要です.例えば,12分サイクルのK線データと4時間のK線サイクルのデータが必要です.通常,そのような非標準サイクルは直接利用できません.それでは,そのようなニーズに対処するにはどうすればよいですか?
非標準サイクルのK線データは,より小さなサイクルのデータを組み合わせることで得ることができる.これをイメージすると,複数のサイクルの最も高い価格は,複数のサイクルのK線合成後の最も高い価格として数えられ,最も低い価格は,合成後の最低価格として計算され,開口価格は変化しない.Kラインの原材料データの最初の開口価格が合成される.閉じる価格は,Kラインの最後の原材料データの閉じる価格に対応する.時間は開口価格の時間を使用する.取引量は,合計して計算した原材料データを使用する.
図のように:
ブロックチェーンの資産BTC_USDTを例として 1時間から4時間を合成します
時間 | 最も高い | オープン | 最低値 | 近づいて |
---|---|---|---|---|
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
データが一致しているのがわかります
初期アイデアを理解した後 要求事項を実現するために コードを手動で書くことができます
このコードは参照のみです.
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線配列構造のデータを返します.
ご注意ください:
目標サイクルは,GetNewCycleRecords関数でデータへの原材料として渡したK線のサイクルのより小さくすることはできません. なぜなら,より小さなサイクルのデータをより大きなサイクルで合成することはできません. ただ,その逆です.
目標サイクルは,
例えば
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分サイクルの場合,閉まっていないサイクルになります.このようなサイクルの計算によるデータは,合成されたデータの開始点によって異なるため,ユニークではありません.
リアルマーケットで実行します.
コントラスト交換図
K線全体で最高価格の移動平均を計算します.
通常,我々は閉店価格の平均を使用して移動平均を計算しますが,時には最高価格,最低価格,開店価格,などを使用する需要があります.
これらの追加要求では,Exchange.GetRecords ((() 機能が返したK行データを直接指標計算機能に転送することはできません.
例えば:
についてtalib.MA
移動平均指標の計算機能には 2 つのパラメータがあり,最初のパラメータは送信する必要があるデータで,もう1つは指標サイクルのパラメータです.
例えば,下記のように指標を計算する必要があります.
K線周期は4時間です
証券市場表では,周期パラメータが9で平均線が設定されています.
計算されたデータソースは,バーあたり最高価格を使用しています.
つまり,この移動平均線は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.長さ-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)
}
}
バックテスト:
マウスの位置は11466.9289です
上記のコードはテストを実行するための戦略にコピーできます.
FMZ Quant プラットフォームには既に パッケージ化されたインターフェースがあり,
exchange.GetRecords
K線データを得るため
数据を取得するために,いくつかの場合,より多くのKラインを取得するためにパラメータを指定する必要がありますので,パッケージGetRecords
初期に100K行以上を必要とする戦略に出くわす場合は,収集プロセスを待たなければなりません.
できるだけ早く戦略を動かすために 関数をカプセル化し 交換所のK線インターフェースに直接アクセスし 参数でより多くのK線データを取得できます
Huobi の取引所での BTC_USDT 取引ペアを例に挙げると,次の要件を実行します.
Exchange の API ドキュメンテーションを見つけ,K-line インターフェースの説明を参照してください.
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")
}
記録に書いてあるようにrecords.length
300 です.つまり,records
K線データバーは300です