Przejdź do treści

Pobieranie danych symbolu

Pobieranie i interpretowanie danych symbolu (na przykład cen otwarcia i zamknięcia wszystkich słupków z określonego okresu) jest niezbędne w każdej aplikacji oferującej którąkolwiek z poniższych funkcji:

  • Wykresy – do tworzenia wykresów słupkowych lub liniowych potrzebne są zarówno historyczne, jak i bieżące dane słupków oraz kwotowań.
  • Statystyki rynkowe – aby wyświetlać statystyki rynkowe (takie jak dzienne zmiany cen poszczególnych symboli), musisz pobierać zarówno ceny historyczne, jak i bieżące.
  • Odtwarzanie – w swojej aplikacji możesz umożliwić traderom powrót do wcześniejszego okresu i handel na danych historycznych. W tym celu musisz pobierać i przetwarzać historyczne dane słupków i ticków.

W tym samouczku pokażemy, jak pobierać i przetwarzać historyczne oraz bieżące dane słupków i ticków, a także kwotowania głębokości rynku w czasie rzeczywistym.

Pamiętaj, że samouczek zawiera fragment kodu wyłącznie do pobierania historycznych danych słupków. Ponieważ podstawowa logika pozostaje taka sama niezależnie od wykonywanej czynności, możesz dostosować ten fragment kodu do pobierania innych typów danych.

Praca z JSON

Podczas pracy z JSON również możesz wykorzystać kod z tego samouczka, jednak musisz go nieco zmodyfikować w zależności od przyjętego sposobu serializacji i deserializacji.

Pobieranie historycznych danych słupków

Aby otrzymać historyczne dane słupków, wykonaj następujące czynności:

  • Zainicjuj obiekt reprezentujący komunikat ProtoOAGetTrendbarsReq.
  • Uzupełnij właściwości obiektu wymaganymi wartościami ctidTraderAccountId, symbolId, ProtoOATrendbarPeriod, liczbą słupków do zwrócenia count oraz znacznikami czasu Unix toTimestamp i fromTimestamp.

Ograniczenia znaczników czasu

Pamiętaj, że istnieją ograniczenia dotyczące maksymalnej możliwej różnicy między toTimestamp a fromTimestamp. Ograniczenia te zależą od określonej wartości ProtoOATrendPeriod. Aby dowiedzieć się więcej, kliknij tutaj.

  • Wyślij nowo utworzony komunikat i odbierz odpowiedź typu ProtoOAGetTrendbarsRes. Odczytaj pole trendbar, aby uzyskać listę słupków.
  • Przekształć dane z formatu względnego na rzeczywistą cenę symbolu. W tym celu najpierw pobierz cenę minimalną słupka i podziel ją przez 100000. Następnie zaokrąglij wynik do liczby miejsc dziesiętnych symbolu (na przykład dwóch cyfr po separatorze dziesiętnym). Aby uzyskać cenę maksymalną, cenę otwarcia i cenę zamknięcia słupka, dodaj deltę każdej z tych cen do ceny minimalnej słupka. Następnie podziel każdą liczbę przez 100000 i zaokrąglij wynik do liczby miejsc dziesiętnych symbolu.

Możesz wykonać te czynności, korzystając z poniższego kodu.

 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

Pobieranie historycznych danych tickowych

Aby otrzymać historyczne dane tickowe, wykonaj następujące czynności:

  • Zainicjuj obiekt reprezentujący komunikat ProtoOAGetTickDataReq.
  • Uzupełnij właściwości obiektu wymaganymi wartościami ctidTraderAccountId, symbolId, typem kwotowania type oraz wartościami fromTimestamp i toTimestamp.

Ograniczenia znaczników czasu

Nie można żądać historycznych danych tickowych za okres dłuższy niż tydzień. Dlatego różnica między określonymi wartościami toTimestamp i fromTimestamp nie może przekraczać 604800000.

  • Wyślij nowo utworzony komunikat i odbierz odpowiedź typu ProtoOAGetTickDataRes. Odczytaj pole tickData, aby uzyskać listę elementów typu ProtoOATickData.
  • Przekształć dane z formatu względnego na rzeczywistą cenę symbolu. W tym celu podziel wartość każdego ticka przez 100000 i zaokrąglij wynik do liczby miejsc dziesiętnych symbolu.

Żądanie dużej liczby ticków

Istnieje limit liczby ticków, które mogą zostać zwrócone w komunikacie ProtoOAGetTickDataRes. Jeśli ten limit zostanie przekroczony (na przykład w określonym okresie wystąpiło bardzo wiele ticków), komunikat ProtoOAGetTickDataRes będzie zawierał tylko pierwsze X ticków, gdzie X jest liczbą mniejszą od limitu ticków. Dokładny limit zależy od konfiguracji backendu cTrader.

Aby sprawdzić, czy istnieje więcej ticków niż zwrócono w otrzymanym komunikacie, użyj flagi hasMore.

Pobieranie danych słupków w czasie rzeczywistym

Aby otrzymywać słupki w czasie rzeczywistym, wykonaj następujące czynności:

  • Zainicjuj zmienną reprezentującą komunikat ProtoOAGetTrendbarsReq.
  • Uzupełnij właściwości obiektu wymaganymi wartościami ctidTraderAccountId, symbolId, ProtoOATrendbarPeriod, liczbą słupków do zwrócenia count oraz znacznikami czasu Unix toTimestamp i fromTimestamp.

Ograniczenia znaczników czasu

Istnieją ograniczenia dotyczące maksymalnej możliwej różnicy między toTimestamp a fromTimestamp. Ograniczenia te zależą od określonej wartości ProtoOATrendPeriod. Aby dowiedzieć się więcej, kliknij tutaj.

  • Wyślij nowo utworzony komunikat i odbierz odpowiedź typu ProtoOAGetTrendbarsRes. Odczytaj pole trendbar, aby uzyskać listę słupków.

  • Przekształć dane z formatu względnego na rzeczywistą cenę symbolu. W tym celu najpierw pobierz cenę minimalną słupka i podziel ją przez 100000. Następnie zaokrąglij wynik do liczby miejsc dziesiętnych symbolu (na przykład dwóch cyfr po separatorze dziesiętnym). Aby uzyskać cenę maksymalną, cenę otwarcia i cenę zamknięcia słupka, dodaj deltę każdej z tych cen do ceny minimalnej słupka. Następnie podziel każdą liczbę przez 100000 i zaokrąglij wynik do liczby miejsc dziesiętnych symbolu.

  • Zainicjuj obiekt reprezentujący komunikat ProtoOASubscribeLiveTrendbarReq.

  • Uzupełnij właściwości obiektu wymaganymi wartościami ctidTraderAccountId, ProtoOATrendbarPeriod i symbolId.

  • Zrób to samo z obiektem reprezentującym komunikat ProtoOASubscribeSpotsReq.

  • Wyślij kolejno komunikaty ProtoOASubscribeSpotsReq i ProtoOASubscribeLiveTrendbarReq, a następnie odbierz odpowiedzi typu ProtoOASubscribeSpotsRes i ProtoOASubscribeLiveTrenbarsRes. W tym momencie subskrypcja danych słupków w czasie rzeczywistym jest aktywna i powinny przychodzić komunikaty typu ProtoOASpotEvent.

Subskrypcja słupków w czasie rzeczywistym

Aby skutecznie subskrybować słupki w czasie rzeczywistym, musisz najpierw zasubskrybować zdarzenia spot.

  • Po otrzymaniu nowego komunikatu ProtoOASpotEvent użyj jego pola trendbar, aby uzyskać dane ostatniego zamkniętego słupka.
  • Przekształć dane z formatu względnego na rzeczywiste ceny symbolu. W tym celu najpierw pobierz cenę minimalną słupka i podziel ją przez 100000. Następnie zaokrąglij wynik do liczby miejsc dziesiętnych symbolu (na przykład dwóch cyfr po separatorze dziesiętnym). Aby uzyskać cenę maksymalną, cenę otwarcia i cenę zamknięcia słupka, dodaj deltę każdej z tych cen do ceny minimalnej słupka. Następnie podziel każdą liczbę przez 100000 i zaokrąglij wynik do liczby miejsc dziesiętnych symbolu.

Aby anulować subskrypcję danych słupków w czasie rzeczywistym, możesz w dowolnym momencie wysłać komunikat ProtoOAUnsubscribeLiveTrendbarsReq zawierający symbolId, period i Twój ctidTraderAccountId. Jeśli żądanie zostanie zrealizowane, powinna nadejść odpowiedź typu ProtoOAUnsubscribeLiveTrenbarRes. Subskrypcja zdarzeń spot pozostanie aktywna.

Pobieranie kwotowań w czasie rzeczywistym

Aby otrzymywać kwotowania bid i ask symbolu w czasie rzeczywistym, wykonaj następujące czynności:

  • Zainicjuj obiekt reprezentujący komunikat ProtoOASubscribeSpotsReq.
  • Uzupełnij właściwości obiektu wartościami ctidTraderAccountId, symbolId oraz, opcjonalnie, wartością logiczną subscribeToSpotTimestamp.
  • Wyślij nowo utworzony komunikat i odbierz odpowiedź typu ProtoOASubscribeSpotsRes. W tym momencie subskrypcja kwotowań w czasie rzeczywistym jest aktywna i powinny przychodzić komunikaty typu ProtoOASpotEvent.
  • Po otrzymaniu nowego komunikatu ProtoOASpotEvent odczytaj jego pola bid i ask, aby uzyskać najnowsze kwotowania. Pamiętaj, że nadal musisz przekształcić dane na rzeczywistą cenę, dzieląc je przez 100000 i zaokrąglając do liczby miejsc dziesiętnych symbolu.

Pola bid i ask

Ponieważ pola bid i ask są opcjonalne, nie każdy komunikat ProtoOASpotEvent musi zawierać oba pola.

Aby anulować subskrypcję kwotowań, możesz w dowolnym momencie wysłać komunikat ProtoOAUnsubscribeSpotsReq zawierający symbolId i Twój ctidTraderAccountId. Jeśli żądanie zostanie zrealizowane, powinna nadejść odpowiedź typu ProtoOAUnsubscribeSpotsRes. Od tego momentu zdarzenia spot nie powinny już przychodzić.

Kwotowania głębokości rynku

Możesz również otrzymywać kwotowania głębokości rynku, czyli kwotowania poziomu II, dla symbolu w czasie rzeczywistym. W tym celu wykonaj następujące czynności.

Za pośrednictwem API możesz subskrybować i otrzymywać kwotowania głębokości rynku, czyli kwotowania poziomu II, dla symbolu w czasie rzeczywistym.

  • Zainicjuj obiekt reprezentujący komunikat ProtoOASubscribeDepthQuotesReq.
  • Uzupełnij właściwości obiektu wartościami ctidTraderAccountId i symbolId.
  • Wyślij nowo utworzony komunikat i odbierz odpowiedź typu ProtoOASubscribeDepthQuotesRes. W tym momencie subskrypcja kwotowań głębokości rynku jest aktywna, więc powinny zacząć przychodzić komunikaty ProtoOADepthEvent.
  • Po otrzymaniu nowego komunikatu ProtoOADepthEvent użyj jego pól newQuotes i deletedQuotes, aby uzyskać najnowsze dane głębokości rynku. Musisz również przekształcić dane na rzeczywistą cenę, dzieląc je przez 100000 i zaokrąglając wynik do liczby miejsc dziesiętnych symbolu. Musisz także przeliczyć wielkość kwotowania głębokości rynku na jednostki, dzieląc ją przez 100.

Aby anulować subskrypcję zdarzeń głębokości rynku, możesz w dowolnym momencie użyć komunikatu ProtoOAUnsubscribeDepthQuotesReq, podając symbolId i ctidTraderAccountId. Powinien nadejść komunikat typu ProtoOAUnsubscribeDepthQuotesRes; od tego momentu zdarzenia głębokości rynku nie powinny już przychodzić.