跳转至

获取符号数据

获取和解释符号数据(例如,特定时间段内所有柱的开盘价和收盘价)在任何具有以下功能的应用程序中都是必不可少的:

  • 图表 – 要构建柱状图或折线图,您需要了解历史和实时的柱和报价数据。
  • 市场统计 – 如果您想显示市场统计信息(例如各个符号的每日价格变化),您必须获取历史和实时价格。
  • 回放 – 在您的应用程序中,您可能允许交易者回到之前的时期并在历史数据上进行交易。 为此,您需要获取和处理过去的柱和跳动点数据。

在本教程中,我们将展示如何获取和处理历史和实时的柱和跳动点数据,以及实时的深度报价。

请注意,本教程仅提供了获取历史柱数据的代码片段。 由于无论您执行什么操作,核心逻辑都保持不变,您可以调整此片段以获取其他类型的数据。

操作 JSON

在操作 JSON 时,您仍然可以重用本教程中的代码;但是,您需要根据您的序列化和反序列化方法对其进行轻微修改。

获取历史柱数据

要接收历史柱数据,请执行以下操作:

  • 初始化一个表示 ProtoOAGetTrendbarsReq 消息 的对象。
  • 使用所需的 ctidTraderAccountIdsymbolIdProtoOATrendbarPeriod、要返回的柱数量以及 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 消息 的对象。
  • 填充对象属性,包括所需的 ctidTraderAccountIdsymbolId、报价 type 以及 fromTimestamptoTimestamp

时间戳限制

无法请求超过一周的历史报价数据。 因此,指定的 toTimestampfromTimestamp 之间的差值不得大于 604800000

  • 发送新创建的消息并接收 ProtoOAGetTickDataRes 类型 的响应。 访问其 tickData 字段以获取 ProtoOATickData 类型的元素列表。
  • 将数据从相对格式转换为实际符号价格。 为此,将每个报价除以100000并将结果四舍五入到符号位数。

请求大量报价

返回的 ProtoOAGetTickDataRes 消息中的报价数量存在限制。 如果超过此限制(例如,在指定期间内有大量报价),ProtoOAGetTickDataRes 消息将仅包含前X个报价,其中X是低于报价限制的数字。 确切限制取决于cTrader后端的配置。

要检查是否存在比接收消息中返回的报价更多的报价,请使用 hasMore 标志。

获取实时柱状数据

要接收实时柱状数据,请执行以下操作:

  • 初始化一个表示 ProtoOAGetTrendbarsReq 消息 的变量。
  • 填充对象属性,包括所需的 ctidTraderAccountIdsymbolIdProtoOATrendbarPeriod、要返回的趋势条 counttoTimestampfromTimestamp Unix时间戳。

时间戳限制

toTimestampfromTimestamp 之间的最大可能距离存在一些限制。 这些限制取决于指定的 ProtoOATrendPeriod。 要了解更多信息,点击此处

  • 发送新创建的消息并接收 ProtoOAGetTrendbarsRes 类型 的响应。 访问其 trendbar 字段以获取趋势条列表。

  • 将数据从相对格式转换为实际符号价格。 为此,首先获取趋势条的低价并将其除以100000。 然后将结果四舍五入到符号位数(例如,分隔符后的两位数)。 要获取趋势条的高价、开盘价和收盘价,将每个价格的趋势条增量加到趋势条的低价上。 然后将每个数字除以100000并将结果四舍五入到符号位数。

  • 初始化一个表示 ProtoOASubscribeLiveTrendbarReq 消息 的对象。

  • 填充对象属性,包括所需的 ctidTraderAccountIdProtoOATrendbarPeriodsymbolId

  • 对表示 ProtoOASubscribeSpotsReq 消息 的对象执行相同的操作。

  • 按顺序发送 ProtoOASubscribeSpotsReq 消息和 ProtoOASubscribeLiveTrendbarReq 消息,并接收 ProtoOASubscribeSpotsResProtoOASubscribeLiveTrenbarsRes 类型 的响应。 此时,您已订阅实时柱状数据,并且应接收 ProtoOASpotEvent 类型 的消息。

订阅实时趋势条

成功订阅实时趋势条首先需要订阅现货事件。

  • 当您接收到新的 ProtoOASpotEvent 消息时,使用其 trendbar 字段获取最后关闭的条的数据。
  • 将数据从相对格式转换为实际符号价格。 为此,首先获取趋势条的低价并将其除以100000。 然后将结果四舍五入到符号位数(例如,分隔符后的两位数)。 要获取趋势条的高价、开盘价和收盘价,将每个价格的趋势条增量加到趋势条的低价上。 然后将每个数字除以100000并将结果四舍五入到符号位数。

要取消订阅实时趋势条数据,您可以随时发送包含 symbolIdperiod 和您的 ctidTraderAccountIdProtoOAUnsubscribeLiveTrendbarsReq 消息。 如果您的请求成功,您应接收 ProtoOAUnsubscribeLiveTrenbarRes 类型 的响应。 您的现货事件订阅仍将保留。

获取实时报价

要接收符号的实时买入和卖出报价,请执行以下操作:

  • 初始化一个表示 ProtoOASubscribeSpotsReq 消息 的对象。
  • 填充对象属性,包括 ctidTraderAccountIdsymbolId,以及可选的 subscribeToSpotTimestamp 布尔值。
  • 发送新创建的消息并接收 ProtoOASubscribeSpotsRes 类型的响应。 此时,您已订阅实时报价数据,并且应接收 ProtoOASpotEvent 类型 的消息。
  • 当您接收到新的 ProtoOASpotEvent 消息时,访问其 bidask 字段以获取最新报价。 请注意,您仍然需要将数据转换为实际价格值,方法是将其除以100000并将其四舍五入到符号位数。

买入和卖出字段

由于 bidask 字段是可选的,您可能不一定看到指定了这两个字段的 ProtoOASpotEvent 消息。

要取消订阅报价数据,您可以随时发送包含 symbolId 和您的 ctidTraderAccountIdProtoOAUnsubscribeSpotsReq 消息。 如果您的请求成功,您应接收 ProtoOAUnsubscribeSpotsRes 类型 的响应。 此时,您应停止接收现货事件。

深度报价

最后但同样重要的是,您还可以接收符号的实时深度或Level II报价。 为此,请执行以下操作。

您可以从API订阅并接收符号的实时深度或Level II报价。

  • 初始化一个表示 ProtoOASubscribeDepthQuotesReq 消息 的对象。
  • 填充对象属性,包括 ctidTraderAccountIdsymbolId
  • 发送新创建的消息并接收 ProtoOASubscribeDepthQuotesRes 类型 的响应。 此时,您已订阅深度报价,这意味着您应开始接收 ProtoOADepthEvent 消息
  • 当您接收到新的 ProtoOADepthEvent 消息时,您需要使用其 newQuotesdeletedQuotes 字段以获取最新深度数据。 您还需要将数据转换为实际价格值,方法是将其除以100000并将结果四舍五入到符号位数。 您还需要将深度报价大小转换为单位,方法是将其除以100。

要取消订阅深度事件,您可以随时使用 ProtoOAUnsubscribeDepthQuotesReq 消息,同时指定 symbolIdctidTraderAccountId。 您应接收 ProtoOAUnsubscribeDepthQuotesRes 类型 的消息;之后,您应停止接收深度事件。