콘텐츠로 이동

심벌 데이터 획득

심벌 데이터를 획득하고 해석하는 것은(예: 특정 기간 동안의 모든 바의 시가와 종가) 다음 기능 중 하나라도 있는 모든 애플리케이션에서 필수적입니다:

  • 차트 – 바 또는 선 차트를 구성하려면 과거 및 실시간 바와 시세 데이터를 알아야 합니다.
  • 시장 통계 – 개별 심벌의 일일 가격 변동과 같은 시장 통계를 표시하려면 과거 및 실시간 가격을 획득해야 합니다.
  • 리플레이 – 애플리케이션에서 트레이더가 이전 기간으로 돌아가 과거 데이터를 기반으로 거래할 수 있도록 허용할 수 있습니다. 이를 위해서는 과거 바와 틱 데이터를 획득하고 처리해야 합니다.

이 튜토리얼에서는 과거 및 실시간 바와 틱 데이터, 그리고 실시간 깊이 시세를 획득하고 처리하는 방법을 보여드리겠습니다.

튜토리얼에서는 과거 바 데이터를 획득하는 코드 스니펫만 제공합니다. 핵심 로직은 수행하는 작업에 관계없이 동일하므로 이 스니펫을 다른 유형의 데이터를 획득하도록 적응할 수 있습니다.

JSON 작업

JSON 작업 시에도 이 튜토리얼의 코드를 재사용할 수 있습니다. 그러나 직렬화 및 역직렬화 접근 방식에 따라 약간 수정해야 할 수 있습니다.

과거 바 데이터 획득

과거 바 데이터를 수신하려면 다음 작업을 수행하십시오:

  • ProtoOAGetTrendbarsReq 메시지를 나타내는 객체를 초기화합니다.
  • 객체 속성을 필요한 ctidTraderAccountId, symbolId, ProtoOATrendbarPeriod, 반환할 트렌드바의 count, 그리고 toTimestampfromTimestamp Unix 타임스탬프로 채웁니다.

타임스탬프 제약 조건

toTimestampfromTimestamp 사이의 최대 가능한 거리에 대한 일부 제약 조건이 있음에 유의하세요. 이러한 제약 조건은 지정된 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, 인용 typefromTimestamptoTimestamp로 객체 속성을 채우세요.

타임스탬프 제약 조건

일주일 이상의 기간에 대한 과거 틱 데이터를 요청하는 것은 불가능합니다. 따라서 지정된 toTimestampfromTimestamp 사이의 차이는 604800000보다 크지 않아야 합니다.

  • 새로 생성된 메시지를 보내고 ProtoOAGetTickDataRes 타입의 응답을 받으세요. tickData 필드에 접근하여 ProtoOATickData 타입의 요소 목록을 얻으세요.
  • 데이터를 상대 형식에서 실제 심볼 가격으로 변환하세요. 이를 위해 각 틱을 100000으로 나누고 결과를 심볼 자릿수로 반올림하세요.

많은 수의 틱 요청

ProtoOAGetTickDataRes 메시지에서 반환될 수 있는 틱 수에 제한이 있습니다. 이 제한을 초과하면(예: 지정된 기간 동안 상당한 수의 틱이 발생한 경우), ProtoOAGetTickDataRes 메시지는 첫 X개의 틱만 포함하며, 여기서 X는 틱 제한보다 낮은 숫자입니다. 정확한 제한은 cTrader 백엔드의 구성에 따라 다릅니다.

받은 메시지에서 반환된 것보다 더 많은 틱이 있는지 확인하려면 hasMore 플래그를 사용하세요.

실시간 바 데이터 얻기

실시간 바를 받으려면 다음 작업을 수행하세요:

  • ProtoOAGetTrendbarsReq 메시지를 나타내는 변수를 초기화하세요.
  • 필요한 ctidTraderAccountId, symbolId, ProtoOATrendbarPeriod, 반환할 트렌드 바의 count, toTimestampfromTimestamp Unix 타임스탬프로 객체 속성을 채우세요.

타임스탬프 제약 조건

toTimestampfromTimestamp 사이의 최대 가능한 거리에 대한 일부 제약 조건이 있습니다. 이러한 제약 조건은 지정된 ProtoOATrendPeriod에 따라 다릅니다. 자세히 알아보려면 여기를 클릭하세요.

  • 새로 생성된 메시지를 보내고 ProtoOAGetTrendbarsRes 타입의 응답을 받으세요. trendbar 필드에 접근하여 트렌드 바 목록을 얻으세요.

  • 데이터를 상대 형식에서 실제 심볼 가격으로 변환하세요. 이를 위해 먼저 트렌드 바의 낮은 가격을 얻어 100000으로 나눕니다. 그런 다음 결과를 심볼 자릿수로 반올림합니다(예: 구분자 뒤의 두 숫자). 트렌드 바의 높은 가격, 시작 가격 및 종가를 얻으려면 각 가격의 트렌드 바 델타를 트렌드 바의 낮은 가격에 더하세요. 그런 다음 각 숫자를 100000으로 나누고 결과를 심볼 자릿수로 반올림하세요.

  • ProtoOASubscribeLiveTrendbarReq 메시지를 나타내는 객체를 초기화하세요.

  • 필요한 ctidTraderAccountId, ProtoOATrendbarPeriodsymbolId로 객체 속성을 채우세요.

  • ProtoOASubscribeSpotsReq 메시지를 나타내는 객체에 대해서도 동일하게 수행하세요.

  • ProtoOASubscribeSpotsReq 메시지와 ProtoOASubscribeLiveTrendbarReq 메시지를 순서대로 보내고 ProtoOASubscribeSpotsResProtoOASubscribeLiveTrenbarsRes 타입의 응답을 받으세요. 이 시점에서 실시간 바 데이터에 구독되었으며 ProtoOASpotEvent 타입의 메시지를 받아야 합니다.

실시간 트렌드 바 구독

실시간 트렌드 바를 성공적으로 구독하려면 먼저 스팟 이벤트에 대한 구독이 필요합니다.

  • 새로운 ProtoOASpotEvent 메시지를 받으면, 해당 메시지의 trendbar 필드를 사용하여 마지막으로 종료된 바의 데이터를 가져옵니다.
  • 상대적 형식의 데이터를 실제 심볼 가격으로 변환합니다. 이를 위해 먼저 트렌드 바의 낮은 가격을 얻어 100000으로 나눕니다. 그런 다음 결과를 심볼 자릿수로 반올림합니다(예: 구분자 뒤의 두 숫자). 트렌드 바의 높은 가격, 시작 가격 및 종가를 얻으려면 각 가격의 트렌드 바 델타를 트렌드 바의 낮은 가격에 더하세요. 그런 다음 각 숫자를 100000으로 나누고 결과를 심볼 자릿수로 반올림하세요.

라이브 트렌드바 데이터 구독을 취소하려면, symbolId, periodctidTraderAccountId를 포함한 ProtoOAUnsubscribeLiveTrendbarsReq 메시지를 보낼 수 있습니다. 요청이 성공하면, ProtoOAUnsubscribeLiveTrenbarRes 타입의 응답을 받아야 합니다. 스팟 이벤트에 대한 구독은 여전히 유지됩니다.

라이브 호가 얻기

심볼에 대한 라이브 매도 및 매수 호가를 받으려면 다음 작업을 수행하세요:

  • ProtoOASubscribeSpotsReq 메시지를 나타내는 객체를 초기화합니다.
  • 객체 속성에 ctidTraderAccountId, symbolId 및 선택적으로 subscribeToSpotTimestamp bool을 채웁니다.
  • 새로 생성된 메시지를 보내고 ProtoOASubscribeSpotsRes 타입의 응답을 받습니다. 이 시점에서 라이브 호가 데이터에 구독되었으며, ProtoOASpotEvent 타입의 메시지를 받아야 합니다.
  • 새로운 ProtoOASpotEvent 메시지를 받으면, 해당 메시지의 bidask 필드에 접근하여 최신 호가를 얻습니다. 데이터를 실제 가격 값으로 변환하려면 100000으로 나누고 심볼 자릿수로 반올림해야 합니다.

매도 및 매수 필드

bidask 필드는 선택적이므로, 두 필드가 모두 지정된 ProtoOASpotEvent 메시지를 반드시 볼 수는 없습니다.

호가 데이터 구독을 취소하려면, symbolIdctidTraderAccountId를 포함한 ProtoOAUnsubscribeSpotsReq 메시지를 보낼 수 있습니다. 요청이 성공하면, ProtoOAUnsubscribeSpotsRes 타입의 응답을 받아야 합니다. 이 시점에서 스팟 이벤트를 더 이상 받지 않아야 합니다.

깊이 호가

마지막으로, 심볼에 대한 라이브 깊이 또는 레벨 II 호가를 받을 수도 있습니다. 이를 위해 다음 작업을 수행하세요.

API에서 심볼에 대한 라이브 깊이 또는 레벨 II 호가를 구독하고 받을 수 있습니다.

  • ProtoOASubscribeDepthQuotesReq 메시지를 나타내는 객체를 초기화합니다.
  • 객체 속성에 ctidTraderAccountIdsymbolId를 채웁니다.
  • 새로 생성된 메시지를 보내고 ProtoOASubscribeDepthQuotesRes 타입의 응답을 받습니다. 이 시점에서 깊이 호가에 구독되었으며, ProtoOADepthEvent 메시지를 받기 시작해야 합니다.
  • 새로운 ProtoOADepthEvent 메시지를 받으면, 해당 메시지의 newQuotesdeletedQuotes 필드를 사용하여 최신 깊이 데이터를 얻습니다. 또한 데이터를 실제 가격 값으로 변환하려면 100000으로 나누고 결과를 심볼 자릿수로 반올림해야 합니다. 깊이 호가 크기를 단위로 변환하려면 100으로 나눕니다.

깊이 이벤트 구독을 취소하려면, symbolIdctidTraderAccountId를 지정하여 ProtoOAUnsubscribeDepthQuotesReq 메시지를 사용할 수 있습니다. ProtoOAUnsubscribeDepthQuotesRes 타입의 메시지를 받아야 하며, 이후 깊이 이벤트를 더 이상 받지 않아야 합니다.