При разработке некоторых трендовых стратегий, вычислительные показатели часто требуют достаточное количество K-линий Bar; полагаются на API платформы FMZ:exchange.GetRecords()
И мы можем вычислить, что мы можем сделать.exchange.GetRecords()
В ранних дизайнах API криптовалютных бирж не было разделения страниц на запросы, поэтому некоторые разработчики не могли удовлетворить потребности в вычислении показателей с большими параметрами.
Если K-линейный интерфейс Binance Contract API поддерживает разделение запросов, то эта статья покажет вам, как сделать разделение запросов с помощью Binance K-линейного интерфейса API.
Сначала нужно посмотреть на документацию API биржи, чтобы увидеть конкретные параметры интерфейса. Мы можем увидеть, что при вызове интерфейса K-линия требуется указать разновидность, цикл K-линии, диапазон данных ((начало, время окончания), количество разделов и т. д.).
Поскольку мы спроектировали запрос на определенное количество данных K-линий, например, запрос на 1 час K-линий, перемещенный из текущего момента в прошлое время, в количестве 5000 бар. Таким образом, если вы вызовите только один запрос API-интерфейса биржи, то, очевидно, вы не получите нужных данных.
Затем мы разделяем страницы запросов и обрабатываем их в сегментах от текущего момента до определенного момента в истории. Мы знаем, что циклы K-линейных данных, которые нам нужны, хорошо вычисляют время начала и окончания каждого сегмента.
Интерфейсные функции шаблона:$.GetRecordsByLength(e, period, length)
。
/**
* desc: $.GetRecordsByLength 是该模板类库的接口函数,该函数用于获取指定K线长度的K线数据
* @param {Object} e - 交易所对象
* @param {Int} period - K线周期,秒数为单位
* @param {Int} length - 指定获取的K线数据的长度,具体和交易所接口限制有关
* @returns {Array<Object>} - K线数据
*/
Дизайн$.GetRecordsByLength
Эта функция обычно требует длинных K-линий для вычисления показателей в начале выполнения стратегии. После выполнения этой функции достаточно длинные данные, после чего нужно только обновить новые данные K-линий. Не нужно больше вызывать эту функцию для получения очень длинных данных K-линий, что приводит к ненужным вызовам интерфейсов.
Также необходимо разработать интерфейс для последующих обновлений данных:$.UpdataRecords(e, records, period)
。
/**
* desc: $.UpdataRecords 是该模板类库的接口函数,该函数用于更新K线数据
* @param {Object} e - 交易所对象
* @param {Array<Object>} records - 需要更新的K线数据源
* @param {Int} period - K线周期,需要和records参数传入的K线数据周期一致
* @returns {Bool} - 是否更新成功
*/
Следующим шагом является реализация этих интерфейсных функций.
/**
* desc: $.GetRecordsByLength 是该模板类库的接口函数,该函数用于获取指定K线长度的K线数据
* @param {Object} e - 交易所对象
* @param {Int} period - K线周期,秒数为单位
* @param {Int} length - 指定获取的K线数据的长度,具体和交易所接口限制有关
* @returns {Array<Object>} - K线数据
*/
$.GetRecordsByLength = function(e, period, length) {
if (!Number.isInteger(period) || !Number.isInteger(length)) {
throw "params error!"
}
var exchangeName = e.GetName()
if (exchangeName == "Futures_Binance") {
return getRecordsForFuturesBinance(e, period, length)
} else {
throw "not support!"
}
}
/**
* desc: getRecordsForFuturesBinance 币安期货交易所获取K线数据函数的具体实现
* @param {Object} e - 交易所对象
* @param {Int} period - K线周期,秒数为单位
* @param {Int} length - 指定获取的K线数据的长度,具体和交易所接口限制有关
* @returns {Array<Object>} - K线数据
*/
function getRecordsForFuturesBinance(e, period, length) {
var contractType = e.GetContractType()
var currency = e.GetCurrency()
var strPeriod = String(period)
var symbols = currency.split("_")
var baseCurrency = ""
var quoteCurrency = ""
if (symbols.length == 2) {
baseCurrency = symbols[0]
quoteCurrency = symbols[1]
} else {
throw "currency error!"
}
var realCt = e.SetContractType(contractType)["instrument"]
if (!realCt) {
throw "realCt error"
}
// m -> 分钟; h -> 小时; d -> 天; w -> 周; M -> 月
var periodMap = {}
periodMap[(60).toString()] = "1m"
periodMap[(60 * 3).toString()] = "3m"
periodMap[(60 * 5).toString()] = "5m"
periodMap[(60 * 15).toString()] = "15m"
periodMap[(60 * 30).toString()] = "30m"
periodMap[(60 * 60).toString()] = "1h"
periodMap[(60 * 60 * 2).toString()] = "2h"
periodMap[(60 * 60 * 4).toString()] = "4h"
periodMap[(60 * 60 * 6).toString()] = "6h"
periodMap[(60 * 60 * 8).toString()] = "8h"
periodMap[(60 * 60 * 12).toString()] = "12h"
periodMap[(60 * 60 * 24).toString()] = "1d"
periodMap[(60 * 60 * 24 * 3).toString()] = "3d"
periodMap[(60 * 60 * 24 * 7).toString()] = "1w"
periodMap[(60 * 60 * 24 * 30).toString()] = "1M"
var records = []
var url = ""
if (quoteCurrency == "USDT") {
// GET https://fapi.binance.com /fapi/v1/klines symbol , interval , startTime , endTime , limit
// limit 最大值:1500
url = "https://fapi.binance.com/fapi/v1/klines"
} else if (quoteCurrency == "USD") {
// GET https://dapi.binance.com /dapi/v1/klines symbol , interval , startTime , endTime , limit
// startTime 与 endTime 之间最多只可以相差200天
// limit 最大值:1500
url = "https://dapi.binance.com/dapi/v1/klines"
} else {
throw "not support!"
}
var maxLimit = 1500
var interval = periodMap[strPeriod]
if (typeof(interval) !== "string") {
throw "period error!"
}
var symbol = realCt
var currentTS = new Date().getTime()
while (true) {
// 计算limit
var limit = Math.min(maxLimit, length - records.length)
var barPeriodMillis = period * 1000
var rangeMillis = barPeriodMillis * limit
var twoHundredDaysMillis = 200 * 60 * 60 * 24 * 1000
if (rangeMillis > twoHundredDaysMillis) {
limit = Math.floor(twoHundredDaysMillis / barPeriodMillis)
rangeMillis = barPeriodMillis * limit
}
var query = `symbol=${symbol}&interval=${interval}&endTime=${currentTS}&limit=${limit}`
var retHttpQuery = HttpQuery(url + "?" + query)
var ret = null
try {
ret = JSON.parse(retHttpQuery)
} catch(e) {
Log(e)
}
if (!ret || !Array.isArray(ret)) {
return null
}
// 超出交易所可查询范围,查询不到数据时
if (ret.length == 0 || currentTS <= 0) {
break
}
for (var i = ret.length - 1; i >= 0; i--) {
var ele = ret[i]
var bar = {
Time : parseInt(ele[0]),
Open : parseFloat(ele[1]),
High : parseFloat(ele[2]),
Low : parseFloat(ele[3]),
Close : parseFloat(ele[4]),
Volume : parseFloat(ele[5])
}
records.unshift(bar)
}
if (records.length >= length) {
break
}
currentTS -= rangeMillis
Sleep(1000)
}
return records
}
/**
* desc: $.UpdataRecords 是该模板类库的接口函数,该函数用于更新K线数据
* @param {Object} e - 交易所对象
* @param {Array<Object>} records - 需要更新的K线数据源
* @param {Int} period - K线周期,需要和records参数传入的K线数据周期一致
* @returns {Bool} - 是否更新成功
*/
$.UpdataRecords = function(e, records, period) {
var r = e.GetRecords(period)
if (!r) {
return false
}
for (var i = 0; i < r.length; i++) {
if (r[i].Time > records[records.length - 1].Time) {
// 添加新Bar
records.push(r[i])
// 更新上一个Bar
if (records.length - 2 >= 0 && i - 1 >= 0 && records[records.length - 2].Time == r[i - 1].Time) {
records[records.length - 2] = r[i - 1]
}
} else if (r[i].Time == records[records.length - 1].Time) {
// 更新Bar
records[records.length - 1] = r[i]
}
}
return true
}
В шаблоне мы реализовали только поддержку K-линейного интерфейса Binance Contract.getRecordsForFuturesBinance
Функция также может расширяться для поддержки K-линейного интерфейса для других криптовалютных бирж.
Как видно, в шаблоне не так много кода для реализации этих функций, вероятно, меньше 200 строк. После того, как шаблонный код будет написан, тестирование будет абсолютно неисчерпаемым.
Тест требует скопировать эти шаблоны "К-линия исторических данных шаблона для поиска страниц JavaScript" и "Книга линий класса" в свою собственную политику (вПлощадь стратегииМы создали новую политику, чтобы выбрать эти два шаблона:
Использование "Классовой библиотеки рисунков" происходит потому, что нам нужно изобразить полученные данные из K-линий для наблюдений.
function main() {
LogReset(1)
var testPeriod = PERIOD_M5
Log("当前测试的交易所:", exchange.GetName())
// 如果是期货则需要设置合约
exchange.SetContractType("swap")
// 使用$.GetRecordsByLength获取指定长度的K线数据
var r = $.GetRecordsByLength(exchange, testPeriod, 8000)
Log(r)
// 使用画图测试,方便观察
$.PlotRecords(r, "k")
// 检测数据
var diffTime = r[1].Time - r[0].Time
Log("diffTime:", diffTime, " ms")
for (var i = 0; i < r.length; i++) {
for (var j = 0; j < r.length; j++) {
// 检查重复Bar
if (i != j && r[i].Time == r[j].Time) {
Log(r[i].Time, i, r[j].Time, j)
throw "有重复Bar"
}
}
// 检查Bar连续性
if (i < r.length - 1) {
if (r[i + 1].Time - r[i].Time != diffTime) {
Log("i:", i, ", diff:", r[i + 1].Time - r[i].Time, ", r[i].Time:", r[i].Time, ", r[i + 1].Time:", r[i + 1].Time)
throw "Bar不连续"
}
}
}
Log("检测通过")
Log("$.GetRecordsByLength函数返回的数据长度:", r.length)
// 更新数据
while (true) {
$.UpdataRecords(exchange, r, testPeriod)
LogStatus(_D(), "r.length:", r.length)
$.PlotRecords(r, "k")
Sleep(5000)
}
}
Здесь мы используемvar testPeriod = PERIOD_M5
Это слово, настроить 5-минутный цикл K-линии, указать, чтобы получить 8000 бар.var r = $.GetRecordsByLength(exchange, testPeriod, 8000)
Очень длинные K-линии данных, возвращенные интерфейсом, проходят тест на рисунке:
// 使用画图测试,方便观察
$.PlotRecords(r, "k")
Далее мы проверим данные по этой длинной K-линии:
// 检测数据
var diffTime = r[1].Time - r[0].Time
Log("diffTime:", diffTime, " ms")
for (var i = 0; i < r.length; i++) {
for (var j = 0; j < r.length; j++) {
// 检查重复Bar
if (i != j && r[i].Time == r[j].Time) {
Log(r[i].Time, i, r[j].Time, j)
throw "有重复Bar"
}
}
// 检查Bar连续性
if (i < r.length - 1) {
if (r[i + 1].Time - r[i].Time != diffTime) {
Log("i:", i, ", diff:", r[i + 1].Time - r[i].Time, ", r[i].Time:", r[i].Time, ", r[i + 1].Time:", r[i + 1].Time)
throw "Bar不连续"
}
}
}
Log("检测通过")
1, проверяет, есть ли повторения в строке KBar. 2, проверка последовательности линии KBar (если соседняя Bar имеет равные значения временного отклонения)
После прохождения этих проверок проверяется интерфейс для обновления K-линии.$.UpdataRecords(exchange, r, testPeriod)
Это нормально?
// 更新数据
while (true) {
$.UpdataRecords(exchange, r, testPeriod)
LogStatus(_D(), "r.length:", r.length)
$.PlotRecords(r, "k")
Sleep(5000)
}
Код будет постоянно выводить строки K на графике политики, когда он будет работать на диске, чтобы проверить, правильно ли обновлены или добавлены данные строки KBar.
С помощью доступа к дневным линиям K, настройка доступа к 8000 корням (зная, что до 8000 дней нет данных о рынке), так:
По сравнению с данными на биржевых графиках, мы видим, что суточная линия составляет всего 1309 кодеков:
Посмотрите, как совпадают данные.
Адрес шаблона:"Стандарт K-линейных исторических данных для поиска разделения страниц JavaScript"Адрес шаблона:"Классовая библиотека рисунков".
Приведенные выше шаблоны, стратегический код предназначены только для обучения, обучения и использования. Пожалуйста, оптимизируйте или изменьте их в соответствии с потребностями.