프로그래밍된 거래에서 K-라인 데이터 처리에 대한 간략한 논의
K-라인 데이터를 사용하여 프로그래밍 거래 전략을 작성할 때 일반적으로 12분 기간 K-라인 데이터, 4시간 기간 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시간 주기 데이터로 결합됩니다. 시가는 첫 번째 00:00 시간의 시가입니다: 11382.57
종가는 마지막 종가 즉 03:00 종가 11384.71 입니다.
가장 높은 가격은 여기 최고 가격입니다: 11447.07
가장 낮은 가격은 여기 있습니다: 11365.51
4시간 주기 시작 시간은 00:00, 1시간 K-라인 시작 시간은 2019.8.12 00:00입니다.
거래량은 1시간마다 합산될 수 있습니다(주로 가격이 어떻게 합성되는지 관찰하기 위한 것이며, 이는 거래량 데이터에 표시되지 않습니다). 여기서는 자세히 설명하지 않겠습니다.합성된 4시간 K-라인은 다음과 같습니다.
높음: 11447.07
오픈: 11382.57
낮음: 11365.51
수신: 11384.71
시간 : 2019.8.12 00:00데이터가 일관성을 가지고 있는 것을 볼 수 있습니다.
-
구현할 코드를 작성하세요
예비적인 아이디어를 검증한 후, 이 요구 사항을 예비적으로 구현하기 위한 코드 작성을 시작할 수 있습니다.
코드를 직접 공개하세요. 코드는 참조용일 뿐입니다.
function GetNewCycleRecords (sourceRecords, targetCycle) { // K线合成函数 var ret = [] // 首先获取源K线数据的周期 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++) { // 获取 时区偏移数值 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 } // 测试 function main () { while (true) { var r = exchange.GetRecords() // 原始数据,作为合成K线的基础K线数据,例如要合成4小时K线,可以用1小时K线作为原始数据。 var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4) // 通过 GetNewCycleRecords 函数 传入 原始K线数据 r , 和目标周期, 1000 * 60 * 60 * 4 即 目标合成的周期 是4小时K线数据。 $.PlotRecords(r2, "r2") // 策略类库栏 可以勾选画线类库,调用 $.PlotRecords 画线类库 导出函数 画图。 Sleep(1000) // 每次循环间隔 1000 毫秒,防止访问K线接口获取数据过于频繁,导致交易所限制。 } }사실, K-라인을 합성하려면 두 가지가 필요합니다. 첫 번째는 원료 데이터, 즉 작은 주기의 K-라인 데이터입니다.
var r = exchange.GetRecords()
작은 주기의 K-라인 데이터를 얻었습니다. 두 번째는 합성 기간, 즉 K-라인 데이터 합성의 목표 기간을 명확히 정의하는 것입니다.
그런 다음 GetNewCycleRecords 함수의 알고리즘을 통해 합성된 K-라인 배열 구조의 데이터를 최종적으로 반환할 수 있습니다.
다음 사항에 유의하세요.-
- 대상 주기는 GetNewCycleRecords 함수에 데이터 원시 자료로 전달한 K-라인의 주기보다 작을 수 없습니다.
이는 작은 사이클을 이용해 더 작은 사이클의 데이터를 합성하는 것이 불가능하기 때문입니다.
- 대상 주기는 GetNewCycleRecords 함수에 데이터 원시 자료로 전달한 K-라인의 주기보다 작을 수 없습니다.
-
- 설정된 목표 기간은 마감기간이어야 합니다.
사이클 폐쇄란 무엇인가요?
간단히 말해, 1시간 또는 1일 이내에 목표 주기 시간 범위가 결합되어 폐쇄 루프를 형성합니다.
예:
예를 들어, 12분 주기의 K-라인은 각 시간의 0:00에 시작합니다(예를 들어 0:00). 첫 번째 주기는 다음과 같습니다.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, 총 1시간이 소요됩니다.
13분 주기라면 오픈 사이클이고, 그러한 사이클에서 계산된 데이터는 유일하지 않습니다. 왜냐하면 합성된 데이터는 합성 데이터의 시작점에 따라 달라지기 때문입니다.
- 설정된 목표 기간은 마감기간이어야 합니다.
-
-
K-라인 데이터를 사용하여 필요한 데이터 구조를 구성합니다.
그룹 멤버들은 종종 이렇게 질문합니다: 각 K-라인의 최고 가격의 이동 평균을 계산하고 싶은데, 어떻게 해야 하나요?
일반적으로 이동평균선은 종가의 평균을 구해 이동평균선을 형성하지만, 최고가, 최저가, 시가 등을 계산해야 할 때가 있습니다.
이 시점에서는 그냥 할 수 없습니다.exchange.GetRecords()함수로부터 반환된 K-라인 데이터는 지표 계산 함수에 직접 전달됩니다.예를 들어:
talib.MA 이동 평균 지표 계산 함수에는 두 개의 매개변수가 있습니다. 첫 번째 매개변수는 전달해야 하는 데이터이고 두 번째 매개변수는 지표 기간 매개변수입니다.
예를 들어, 우리는 다음과 같은 지표를 계산하고 싶습니다.

K-라인 주기는 4시간입니다.
거래소 차트에서는 이동평균 기간 매개변수를 9로 하여 이동평균이 설정되었습니다.
그리고 계산을 위한 데이터 소스는 각 바의 가장 높은 가격으로 설정됩니다.

즉, 이 이동 평균은 9개의 4시간 K-라인 막대의 가장 높은 가격을 평균한 것이며, 이는 지표 이동 평균을 구성합니다.직접 데이터를 구성해보고 거래소 차트에서 계산된 데이터와 동일한지 확인해 보겠습니다.
var highs = [] for (var i = 0 ; i < r2.length ; i++) { highs.push(r2[i].High) }이동 평균 지표를 도출하기 위해서는 각 막대의 최고 가격의 평균을 계산해야 합니다.
그런 다음 먼저 각 막대의 최고 가격에 해당하는 각 데이터 요소를 포함하는 배열을 구성해야 합니다.
highs 변수가 처음에는 빈 배열인 것을 볼 수 있고, 그런 다음 r2 캔들스틱 데이터 변수를 탐색합니다(r2를 기억하지 못하시나요? 위의 4시간 캔들스틱을 합성하는 메인 함수의 코드를 살펴보세요).
r2의 각 막대의 최고 가격을 읽으세요(즉, r2[i].High, i는 0에서 r2.length - 1까지 범위에 있으며, 이를 highs로 높입니다. 이런 방식으로 K-라인 데이터 막대와 일대일로 대응하는 데이터 구조가 구성됩니다.이 시점에서 최고치를 talib.MA 함수에 전달하여 이동 평균을 계산할 수 있습니다.
완전한 예:
function main () { while (true) { var r = exchange.GetRecords() var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4) if (!r2) { continue } $.PlotRecords(r2, "r2") // 画出K线 var highs = [] for (var i = 0 ; i < r2.length ; i++) { highs.push(r2[i].High) } var ma = talib.MA(highs, 9) // 用均线指标函数 talib.MA 计算 均线指标 $.PlotLine("high_MA9", ma[ma.length - 2], r2[r2.length - 2].Time) // 使用画线类库把均线指标画在图表上 Sleep(1000) } }백테스트 실행:
그림에서 마우스 위치의 이동평균 지표 값이 다음과 같은 것을 확인할 수 있습니다.
11466.9289위의 코드는 테스트를 실행하기 위한 전략에 복사할 수 있습니다. "Line Drawing Library"를 체크하고 저장하는 것을 잊지 마세요!
-
디지털 화폐 시장에서 K-라인 데이터를 얻는 방법
Inventor 양적 거래 플랫폼에는 이미 exchange.GetRecords 함수라는 패키지 인터페이스가 있는데, 이를 통해 K-라인 데이터를 얻을 수 있습니다.
다음은 더 많은 K-라인을 얻기 위해 매개변수를 지정해야 하는 경우가 있으므로 데이터를 얻기 위해 교환 K-라인 데이터 인터페이스에 직접 액세스하는 것에 초점을 맞춥니다. 캡슐화된 GetRecords 인터페이스
일반적으로 100개가 반환됩니다. 전략에 처음에 100개 이상의 K-라인이 필요한 경우, 수집하고 기다려야 합니다.
전략을 가능한 한 빨리 실행하려면 함수를 직접 캡슐화하고 거래소 K-라인 인터페이스에 직접 액세스하고 매개변수를 지정하여 더 많은 K-라인 데이터를 얻을 수 있습니다.Huobi의 BTC_USDT 거래 쌍을 예로 들면, 우리는 이 요구 사항을 구현합니다.
거래소의 API 문서를 찾아 K-line 인터페이스에 대한 설명을 확인하세요.
https://api.huobi.pro/market/history/kline?period=1day&size=200&symbol=btcusdt매개변수:
매개변수 이름 유형 필수 설명 값 symbol string true 거래 쌍 btcusdt, ethbtc... period string true 데이터 시간 세분성, 즉 각 캔들의 시간 간격을 반환합니다. 1분, 5분, 15분, 30분, 60분, 1일, 1개월, 1주일, 1년 size integer false 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") }Python 버전, Huobi 거래소 인터페이스에 접근하는 예:
#!python3
import json
import urllib2
def GetRecords_Huobi(period, size, symbol):
headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
url = "https://api.huobi.pro/market/history/kline?" + "period=" + period + "&size=" + size + "&symbol=" + symbol
request = urllib2.Request(url)
request.add_header('User-Agent','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6')
opener = urllib2.build_opener()
f= opener.open(request)
ret = f.read().decode('utf-8')
try :
jsonData = json.loads(ret)
records = []
for i in range(len(jsonData["data"]) - 1, -1, -1):
records.append({
"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
except Exception as e:
Log(e)
def main():
r = GetRecords_Huobi("1day", "300", "btcusdt")
Log(len(r))
ext.PlotRecords(r, "K") # 需要引用Python画线类库
Python 버전, Binance Exchange의 K-line 인터페이스에 액세스하는 예:
#!python3
import json
import urllib2
def GetRecords_Huobi(period, size, symbol):
headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
url = "https://api.binance.com/api/v3/klines?symbol=" + symbol + "&interval=" + period
request = urllib2.Request(url)
request.add_header('User-Agent','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6')
opener = urllib2.build_opener()
f= opener.open(request)
ret = f.read().decode('utf-8')
try :
jsonData = json.loads(ret)
records = []
for i in range(len(jsonData)):
records.append({
"Time" : float(jsonData[i][0]),
"High" : float(jsonData[i][2]),
"Open" : float(jsonData[i][1]),
"Low" : float(jsonData[i][3]),
"Close" : float(jsonData[i][4]),
"Volume" : float(jsonData[i][5]),
})
return records
except Exception as e:
Log(e)
def main():
r = GetRecords_Huobi("1m", "300", "BTCUSDT")
Log(len(r))
ext.PlotRecords(r, "K") # 需要引用Python画线类库
로그에서 records.length가 300인 것을 볼 수 있는데, 이는 300개의 K-라인 데이터 레코드 막대가 있다는 것을 의미합니다.

if (((1000 * 60 * 60 * 24) - sourceRecords[i].Time % (1000 * 60 * 60 * 24) + (n * 1000 * 60)) % targetCycle == 0) {
isBegin = true
}
这一句有问题,无法用3小时或6小时k合成日k,只能用1小时,2小时,4小时的k线合成日k
- 1











