Перейти к содержанию

Получение данных инструмента

Получение и интерпретация данных инструмента (например, цен открытия и закрытия всех баров за определенный период) необходимы в любом приложении, обладающем любой из следующих функций:

  • Графики — чтобы построить графики баров или линий, необходимо знать как исторические, так и актуальные данные баров и котировок.
  • Статистика рынка — если вы хотите отображать статистику рынка (например, дневные изменения цены для отдельных инструментов), вам необходимо получить как исторические, так и актуальные цены.
  • Реплеи — в вашем приложении вы можете позволить трейдерам возвращаться к предыдущему периоду и торговать на исторических данных. Для этого вам потребуется получить и обработать прошлые данные баров и тиков.

В этом руководстве мы покажем, как получать и обрабатывать исторические и актуальные данные баров и тиков, а также актуальные котировки глубины рынка.

Обратите внимание, что данное руководство предоставляет фрагмент кода только для получения исторических данных баров. Поскольку основная логика остается одинаковой независимо от выполняемого вами действия, вы можете адаптировать этот фрагмент для получения других типов данных.

Работа с JSON

При работе с JSON вы все еще можете повторно использовать код из этого руководства; однако вам потребуется немного изменить его в зависимости от вашего подхода к сериализации и десериализации.

Получение исторических данных баров

Чтобы получить исторические данные баров, выполните следующие действия:

  • Инициализируйте объект, представляющий сообщение ProtoOAGetTrendbarsReq.
  • Заполните свойства объекта необходимыми ctidTraderAccountId, symbolId, ProtoOATrendbarPeriod, count возвращаемых трендовых баров, а также временными метками Unix toTimestamp и fromTimestamp.

Ограничения временных меток

Обратите внимание, что существуют некоторые ограничения на максимально возможное расстояние между toTimestamp и fromTimestamp. Эти ограничения зависят от указанного ProtoOATrendPeriod. Чтобы узнать больше, нажмите сюда.

  • Отправьте только что созданное сообщение и получите ответ типа ProtoOAGetTrendbarsRes. Обратитесь к его полю trendbar, чтобы получить список трендовых баров.
  • Преобразуйте данные из относительного формата в фактическую цену инструмента. Для этого сначала получите минимальную цену трендового бара и разделите ее на 100000. Затем округлите результат до знаков инструмента (например, до двух цифр после разделителя). Чтобы получить максимальную цену, а также цены открытия и закрытия трендового бара, прибавьте дельту трендового бара для каждой из этих цен к минимальной цене трендового бара. После этого разделите каждое число на 100000 и округлите результат до знаков инструмента.

Вы можете выполнить эти действия, повторно используя код ниже.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private static async void TrendbarRequest(ProtoOATrendbarPeriod period, int accountId, int symbolId, int days)
{
    Console.WriteLine("Sending ProtoOAGetTrendbarsReq...");

    var request = new ProtoOAGetTrendbarsReq
    {
        CtidTraderAccountId = accountId,
        SymbolId = symbolId,
        Period = period,
        FromTimestamp = DateTimeOffset.UtcNow.AddDays(-days).ToUnixTimeMilliseconds(),
        ToTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
    };

    Console.WriteLine($"FromTimestamp: {request.FromTimestamp} | ToTimestamp: {request.ToTimestamp}");

    await _client.SendMessage(request);
}

public static double GetPriceFromRelative(ProtoOASymbol symbol, long relative) => Math.Round(relative / 100000.0, symbol.Digits);

private List<Trendbar> OnHistoricalTrendbarsReceived(ProtoOAGetTrendbarsRes message) 
{
    var trendbars = message.Trendbar;

    var data = new List<Trendbar>();

    foreach (var trendbar in trendbars) 
    {
        data.Add(new Trendbar
        {
            Low = GetPriceFromRelative(symbol, trendbar.Low),
            High = GetPriceFromRelative(symbol, trendbar.Low + (int)trendbar.DeltaHigh),
            Open = GetPriceFromRelative(symbol, trendbar.Low + (int)trendbar.DeltaOpen),
            Close = GetPriceFromRelative(symbol, trendbar.Low + (int)trendbar.DeltaClose),
        }
        );
    }

    return data;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def sendProtoOAGetTrendbarsReq(ctidTraderAccountId, weeks, period, symbolId, clientMsgId = None):
    request = ProtoOAGetTrendbarsReq()
    request.ctidTraderAccountId = ctidTraderAccountId
    request.period = ProtoOATrendbarPeriod.Value(period)
    request.fromTimestamp = int(calendar.timegm((datetime.datetime.utcnow() - datetime.timedelta(weeks=int(weeks))).utctimetuple())) * 1000
    request.toTimestamp = int(calendar.timegm(datetime.datetime.utcnow().utctimetuple())) * 1000
    request.symbolId = int(symbolId)
    deferred = client.send(request, clientMsgId = clientMsgId)

def getPriceFromRelative(symbol, relative): round(relative / 100000.0, symbol.digits)

def onHistoricalTrendbarsReceived(message):

    trendbars = message.trendbars

    data = []

    for trendbar in trenbars:
        data.append(Trendbar(low=getPriceFromRelative(symbol, trendbar.low), high=getPriceFromRelative(symbol, trendbar.low + int(trendbar.deltaHigh)), open=getPriceFromRelative(symbol, trendbar.low + int(trendbar.deltaHigh)), close=getPriceFromRelative(symbol, trendbar.low +int(trendbar.deltaClose))))

    return data

Получение исторических данных тиков

Чтобы получить исторические данные тиков, выполните следующие действия:

  • Инициализируйте объект, представляющий сообщение ProtoOAGetTickDataReq.
  • Заполните свойства объекта необходимыми ctidTraderAccountId, symbolId, type котировки, а также fromTimestamp и toTimestamp.

Ограничения временных меток

Невозможно запросить исторические данные тиков за период, превышающий одну неделю. Таким образом, разница между указанными toTimestamp и fromTimestamp не должна превышать 604800000.

  • Отправьте только что созданное сообщение и получите ответ типа ProtoOAGetTickDataRes. Получите доступ к его полю tickData, чтобы получить список элементов типа ProtoOATickData.
  • Преобразуйте данные из относительного формата в фактическую цену инструмента. Для этого разделите каждый тик на 100000 и округлите результат до количества знаков инструмента.

Запрос большого количества тиков

Существует ограничение на количество тиков, которые могут быть возвращены в сообщении ProtoOAGetTickDataRes. Если это ограничение превышено (например, за указанный период было значительное количество тиков), сообщение ProtoOAGetTickDataRes будет включать только первые X тиков, где X — это число, меньшее лимита тиков. Точное ограничение зависит от конфигурации бэкенда cTrader.

Чтобы проверить, существует ли больше тиков, чем было возвращено в полученном сообщении, используйте флаг hasMore.

Получение актуальных данных баров

Чтобы получить актуальные бары, выполните следующие действия:

  • Инициализируйте переменную, представляющую сообщение ProtoOAGetTrendbarsReq.
  • Заполните свойства объекта необходимыми ctidTraderAccountId, symbolId, ProtoOATrendbarPeriod, count возвращаемых трендовых баров, а также временными метками toTimestamp и fromTimestamp.

Ограничения временных меток

Существуют некоторые ограничения на максимально возможное расстояние между toTimestamp и fromTimestamp. Эти ограничения зависят от указанного ProtoOATrendPeriod. Чтобы узнать больше, нажмите сюда.

  • Отправьте только что созданное сообщение и получите ответ типа ProtoOAGetTrendbarsRes. Обратитесь к его полю trendbar, чтобы получить список трендовых баров.

  • Преобразуйте данные из относительного формата в фактическую цену инструмента. Для этого сначала получите минимальную цену трендового бара и разделите ее на 100000. Затем округлите результат до знаков инструмента (например, до двух цифр после разделителя). Чтобы получить максимальную цену, а также цены открытия и закрытия трендового бара, прибавьте дельту трендового бара для каждой из этих цен к минимальной цене трендового бара. После этого разделите каждое число на 100000 и округлите результат до знаков инструмента.

  • Инициализируйте объект, представляющий сообщение ProtoOASubscribeLiveTrendbarReq.

  • Заполните свойства объекта необходимыми ctidTraderAccountId, ProtoOATrendbarPeriod и symbolId.

  • Сделайте то же самое для объекта, представляющего сообщение ProtoOASubscribeSpotsReq.

  • Отправьте сообщения ProtoOASubscribeSpotsReq и ProtoOASubscribeLiveTrendbarReq в этом порядке и получите ответы типов ProtoOASubscribeSpotsRes и ProtoOASubscribeLiveTrenbarsRes. На этом этапе вы подписаны на данные живых баров, и вы должны получать сообщения типа ProtoOASpotEvent.

Подписка на живые трендовые бары

Для успешной подписки на живые трендовые бары сначала требуется подписка на спот-события.

  • Когда вы получаете новое сообщение ProtoOASpotEvent, используйте его поле trendbar, чтобы получить данные для последнего закрытого бара.
  • Преобразуйте данные из относительного формата в фактические цены инструмента. Для этого сначала получите минимальную цену трендового бара и разделите ее на 100000. Затем округлите результат до знаков инструмента (например, до двух цифр после разделителя). Чтобы получить максимальную цену, а также цены открытия и закрытия трендового бара, прибавьте дельту трендового бара для каждой из этих цен к минимальной цене трендового бара. После этого разделите каждое число на 100000 и округлите результат до знаков инструмента.

Чтобы отписаться от данных живых трендовых баров, вы всегда можете отправить сообщение ProtoOAUnsubscribeLiveTrendbarsReq, содержащее symbolId, period и ваш ctidTraderAccountId. Если ваш запрос выполнен успешно, вы должны получить ответ типа ProtoOAUnsubscribeLiveTrenbarRes. Ваша подписка на спот-события при этом останется активной.

Получение живых котировок

Чтобы получать живые котировки продажи и покупки для инструмента, выполните следующие действия:

  • Инициализируйте объект, представляющий сообщение ProtoOASubscribeSpotsReq.
  • Заполните свойства объекта значениями ctidTraderAccountId, symbolId и, опционально, логическим значением subscribeToSpotTimestamp.
  • Отправьте только что созданное сообщение и получите ответ типа ProtoOASubscribeSpotsRes. На этом этапе вы подписаны на данные живых котировок, и вы должны получать сообщения типа ProtoOASpotEvent.
  • Когда вы получаете новое сообщение ProtoOASpotEvent, обратитесь к его полям bid и ask, чтобы получить последние котировки. Обратите внимание, что вам все еще нужно преобразовать данные в фактическое значение цены, разделив его на 100000 и округлив до знаков инструмента.

Поля bid и ask

Поскольку поля bid и ask являются необязательными, вы можете не увидеть сообщений ProtoOASpotEvent, где указаны оба поля.

Чтобы отписаться от данных котировок, вы всегда можете отправить сообщение ProtoOAUnsubscribeSpotsReq, содержащее symbolId и ваш ctidTraderAccountId. Если ваш запрос выполнен успешно, вы должны получить ответ типа ProtoOAUnsubscribeSpotsRes. На этом этапе вы должны перестать получать спот-события.

Котировки глубины рынка

И наконец, вы также можете получать живые котировки глубины рынка или Level II для инструмента. Для этого выполните следующие действия.

Вы можете подписаться и получать живые котировки глубины рынка или Level II для инструмента из API.

  • Инициализируйте объект, представляющий сообщение ProtoOASubscribeDepthQuotesReq.
  • Заполните свойства объекта значениями ctidTraderAccountId и symbolId.
  • Отправьте только что созданное сообщение и получите ответ типа ProtoOASubscribeDepthQuotesRes. На этом этапе вы подписаны на котировки глубины рынка, что означает, что вы должны начать получать сообщения ProtoOADepthEvent.
  • Когда вы получаете новое сообщение ProtoOADepthEvent, вам нужно будет использовать его поля newQuotes и deletedQuotes, чтобы получить последние данные глубины рынка. Вам также нужно будет преобразовать данные в фактическое значение цены, разделив его на 100000 и округлив результат до знаков инструмента. Вам также нужно будет преобразовать размер котировки глубины рынка в единицы, разделив его на 100.

Чтобы отписаться от событий глубины рынка, вы всегда можете использовать сообщение ProtoOAUnsubscribeDepthQuotesReq, указав symbolId и ctidTraderAccountId. Вы должны получить сообщение типа ProtoOAUnsubscribeDepthQuotesRes; после этого вы должны перестать получать события глубины рынка.