При написании количественной торговой стратегии, используя данные K-линии, часто бывают случаи, когда требуются нестандартные циклические K-линейные данные. например, требуются 12-минутные циклические K-линейные данные и 4-часовые K-линейные циклические данные. Обычно такие нестандартные циклы непосредственно недоступны. Итак, как мы справляемся с такими потребностями?
Нестандартные данные о цикле 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 |
Данные четырех одночасовых циклов объединяются в единые четырехчасовые данные.
Цена открытия - это цена открытия первой линии K в 00:00 время: 11382.57 Цена закрытия - это цена закрытия последней линии k в 03:00: 11384.71 Самая высокая цена - это найти самую высокую цену среди них: 11447,07 Самая низкая цена - это найти самую низкую цену среди них: 11365,51
Примечание: Китайский товарный фьючерсный рынок закрывается в 15:00 в обычный торговый день
Время начала 4-часового цикла - это время начала первой 1-часовой K-линии, т.е. 2019.8.12 00:00
Сумма объема всех 1-часовых k линий используется в качестве этого 4-часового 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-линию, вам нужны две вещи. Первая - это данные о сырье, то есть данные K-линии меньшего цикла.var r = exchange.GetRecords()
чтобы получить более мелкие данные цикла K линии.
Во-вторых, чтобы выяснить размер цикла синтеза, мы используем алгоритм функции GetNewCycleRecords для этого, затем вы можете, наконец, вернуть данные синтезированной структуры массива K-линий.
Пожалуйста, обратите внимание:
Целевой цикл не может быть меньше цикла K-линии, которую вы прошли в функции GetNewCycleRecords в качестве сырья для данных.
Целевой цикл должен быть настроен на
Например:
К-линия 12-минутного цикла начинается с 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 минут, то это будет цикл, который не закрыт. Данные, рассчитанные с помощью такого цикла, не являются уникальными, потому что синтезированные данные различаются в зависимости от отправной точки синтезированных данных.
Запустите его на реальном рынке:
Диаграмма контрастного обмена
Я хочу вычислить скользящую среднюю наивысшей цены для всех K-линий.
Обычно мы рассчитываем скользящие средние, используя средние цены закрытия, но иногда есть спрос на использование самой высокой цены, самой низкой цены, цены открытия и так далее.
для этих дополнительных требований данные строки K, возвращенные функцией exchange.GetRecords ((), не могут быть непосредственно переданы функции расчета показателя.
Например:
Вtalib.MA
Функция расчета показателя скользящей средней имеет два параметра, первый из которых - данные, которые необходимо передать, а второй - параметр цикла показателя.
Например, мы должны рассчитать показатели, как показано ниже.
Цикл К-линии длится 4 часа.
На диаграмме котировок на биржевых рынках установлена средняя линия с параметром цикла 9.
В рассчитанном источнике данных используется самая высокая цена за бар.
То есть, эта скользящая средняя линия состоит из средней наивысшей средней цены девяти 4-часовых циклов K-линии.
Давайте построим данные сами, чтобы увидеть, если это то же самое с данными обмена.
var highs = []
for (var i = 0 ; i < r2.length ; i++) {
highs.push(r2[i].High)
}
Поскольку нам нужно вычислить самую высокую цену каждого Бар, чтобы получить значение показателя скользящей средней, мы должны построить массив, в котором каждый элемент данных имеет самую высокую цену для каждого Бар.
Вы можете видеть, чтоhighs
переменная изначально является пустым массивом, затем мы пересекаем переменную данных k-линии r2 (не помните r2? Посмотрите на код в основной функции, которая синтезирует 4-часовую K-линию выше).
Прочитайте самую высокую цену каждого Бар r2 (т.е. r2[i].Высокий, i варьируется от 0 до r2.длина - 1), затем нажмите вhighs
Таким образом, мы просто построим структуру данных, которая соответствует один к одному с K-линией Data Bar.
В данный момент,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-линии обмена для получения данных, потому что иногда вам нужно указать параметры, чтобы получить больше K-линий, пакетGetRecords
Интерфейс обычно возвращает 100 к линий. Если вы столкнетесь со стратегией, которая поначалу требует более 100 к линий, вам нужно подождать процесс сбора.
Для того, чтобы стратегия работала как можно быстрее, вы можете инкапсулировать функцию, напрямую получить доступ к интерфейсу K-линии биржи и указать параметры для получения большего количества данных K-линии.
Используя торговую пару BTC_USDT на бирже Huobi в качестве примера, мы реализуем следующее требование:
Найдите документацию обмена API и посмотрите описание интерфейса K-line:
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")
}
Вы можете увидеть это на дневнике, отпечатокrecords.length
300, то есть количествоrecords
К-линейная панель данных - 300.