Bloomberg API: how do I associate request with response on IntradayBarRequest?

Thomas Browne picture Thomas Browne · Aug 3, 2013 · Viewed 7.4k times · Source

Unfortunately I am led on the forums to believe (but without 100% certainty) that the Bloomberg Desktop API does not allow more than one IntradayBarRequest or IntradayTickRequest at a time, which is different from HistoricalDataRequest or Subscriptions, where multiple simultaneous requests are allowed.

This question is thus probably moot, unless somebody tells me that the above is not true

If true, then the only way to handle the question below, is to send each new request only after the previous one has been handled.


I am using the Python Bloomberg Desktop API to access subscription (live updating) and historical daily data for financial securities. In both of those cases I can send multiple simultaneous requests, and when the responses come (not necessarily in the order the requests were sent), I can find out which security the response is associated with, using msg.getElement("securityData").getElementAsString("security") in the case of historical data, or in the case of subscription data, by querying the correlationId that I had set beforehand (at subscription request time) using msg.correlationIds()[0].value().

However I don't know how to do this for IntradayBarResponse requests (and WAPI docs are not helpful). These do not seem to have a setable correlationId, nor do they have the above "securityData" field. If I send multiple intradayBarRequests, how can I find out for which security the responses are?

Here is my code (adapted from the API Python examples).

import blpapi  # interface to bloomberg
import time    # will need this for time parsing
from optparse import OptionParser
import pdb     # debugger, when necessary
import csv     # for csv reading
import string  # for string parsing
from pymongo import MongoClient
import inspect
from datetime import datetime
from bson.son import SON


def parseCmdLine():
    parser = OptionParser(description="Retrieve realtime data.")
    parser.add_option("-a",
                      "--ip",
                      dest="host",
                      help="server name or IP (default: %default)",
                      metavar="ipAddress",
                      default="localhost")
    parser.add_option("-p",
                      dest="port",
                      type="int",
                      help="server port (default: %default)",
                      metavar="tcpPort",
                      default=8194)
    parser.add_option("--me",
                      dest="maxEvents",
                      type="int",
                      help="stop after this many events (default: %default)",
                      metavar="maxEvents",
                      default=100000000000)
    parser.add_option("--mongohost",
                      dest="mongohost",
                      default="192.168.1.30")
    parser.add_option("--mongoport",
                      dest="mongoport",
                      type="int",
                      default=27017)

    (options, args) = parser.parse_args()

    return options


def main():
    options = parseCmdLine()

    # connect to MongoDB MONGO MONGO MONGO MONGO ----------------
    print "Connecting to MongoDB"
    print options.mongohost
    print options.mongoport
    client = MongoClient(options.mongohost, options.mongoport) # connect to MongoDB
    db = client.bb # connect to the DB database
    bbsecs = db.bbsecs
    bbticks = db.bbticks
    # now get the securities list


    # Fill SessionOptions
    sessionOptions = blpapi.SessionOptions()
    sessionOptions.setServerHost(options.host)
    sessionOptions.setServerPort(options.port)

    print "connecting to Bloomberg"
    print "Connecting to %s:%d" % (options.host, options.port)

    # Create a Session
    session = blpapi.Session(sessionOptions)

    # Start a Session
    if not session.start():
        print "Failed to start session."
        return

    # open the market data subscription service
    if not session.openService("//blp/mktbar"):
        print "Failed to open //blp/mktbar"
        return
    if not session.openService("//blp/refdata"):
        print "Failed to open //blp/refdata"
        return



    # now startup the subscription list
    # Now open the secs.dat file and read it, append each to subscription list
    maxtimes = bbticks.aggregate([{'$group': {'_id':'$ticker', 'maxtime':{'$max': '$time'}}}]) # get the last updates by ticker
    refDataService = session.getService("//blp/refdata") # start the ref
    for i in maxtimes["result"]:
        ticker = i["_id"]
        tstamp = i["maxtime"]
        request = refDataService.createRequest("IntradayBarRequest")
        request.set("security", ticker)
        request.set("eventType", "TRADE")
        request.set("interval", 1)
        request.set("startDateTime", tstamp)
        request.set("endDateTime", datetime.now())
        print "Sending Request:", ticker
        session.sendRequest(request)

    subscriptions = blpapi.SubscriptionList()
    secdic = dict() # a new dictionary
    for post in bbsecs.find():
        print(post["ticker"])
        # subscribe tick
        #subscriptions.add(str(post["ticker"]), "LAST_PRICE", [], blpapi.CorrelationId("TICK:" + str(post["ticker"])))
        #subscribe 1 minute bars
        subscriptions.add("//blp/mktbar/ticker/"+str(post["ticker"]), 
                          "LAST_PRICE", 
                          "interval=1.0",
                          blpapi.CorrelationId(str(post["ticker"])))
        # setup the dictionary
        secdic[post["bbsecnum"]] = post["ticker"]
    if not session.openService("//blp/refdata"):
        print "Failed to open //blp/refdata"
        return
    # now subscribe
    session.subscribe(subscriptions)


    # HISTORICALHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
    # Obtain previously opened service
    #refDataService = session.getService("//blp/refdata")
    # Create and fill the request for the historical data
    #request = refDataService.createRequest("HistoricalDataRequest")
    #for post in bbsecs.find():  
    #    request.getElement("securities").appendValue(str(post["ticker"]))
    #request.getElement("fields").appendValue("LAST_PRICE")
    #request.set("periodicityAdjustment", "ACTUAL")
    #request.set("periodicitySelection", "DAILY")
    #request.set("startDate", "20100101")
    #request.set("endDate", "20121231")
    #request.set("maxDataPoints", 2000)
    #print "Sending Request:", request
    # Send the request
    #session.sendRequest(request)
    #hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh


    try:
        # Process received events
        eventCount = 0
        while(True):
            # We provide timeout to give the chance to Ctrl+C handling:
            event = session.nextEvent(500)
            for msg in event:
                if event.eventType() == blpapi.Event.SUBSCRIPTION_STATUS:
                    #print "%s - %s" % (msg.correlationIds()[0].value(), msg)
                    print "subscription status"
                elif event.eventType() == blpapi.Event.SUBSCRIPTION_DATA:
                    key = msg.correlationIds()[0].value()
                    if msg.messageType() == "MarketBarStart":
                        open = msg.getElementAsFloat("OPEN")
                        high = msg.getElementAsFloat("HIGH")
                        low = msg.getElementAsFloat("LOW")
                        close = msg.getElementAsFloat("CLOSE")
                        btstamp = msg.getElementAsDatetime("TIME")
                        tstamp = datetime.now()
                        print "bar", key, close, tstamp
                        bbticks.insert({"type": "BAR", "ticker": key, "value": close, \
                                "open": open, "high": high, "low": low, "close": close, \
                                "time": tstamp})
                    elif msg.messageType() == "MarketBarUpdate":
                        close = msg.getElementAsFloat("CLOSE")
                        #print "tick", close,
                        #bbticks.insert({"type": "TICK", "ticker": key, "value": close, "time": tstamp})

                    #if etype == "TRADE":
                    #    if msg.hasElement("LAST_TRADE"):
                    #        key = msg.correlationIds()[0].value(),
                    #        keytype = key[:(key.index(":"))]
                    #        key = key[(key.index(":") + 1):]
                    #        value = msg.getElementAsString("LAST_TRADE")
                    #        timestamp = msg.getElementAsDatetime("TRADE_UPDATE_STAMP_RT")
                    #        print key, value, 
                    #        bbticks.insert({"ticker": key, "value": value, "timestamp": timestamp})

                else:
                    if msg.messageType() == "HistoricalDataResponse":
                        securityData = msg.getElement("securityData")
                        security = securityData.getElementAsString("security")
                        fieldDataArray = securityData.getElement("fieldData")
                        for j in range(0, fieldDataArray.numValues()):
                            fieldData = fieldDataArray.getValueAsElement(j)
                            field = fieldData.getElement(0)
                            tstamp = field.getValueAsDatetime()
                            tstamp = datetime(tstamp.year, tstamp.month, tstamp.day)
                            field = fieldData.getElement(1)
                            close = field.getValueAsFloat()
                            #print "history", security, close, 
                            #bbticks.insert({"type": "DAILY", "ticker": security, "value": close, "close": close, \
                            #        "time": tstamp})
                    elif msg.messageType() == "IntradayBarResponse":
                        print "IntradayBarResponse"
                        data = msg.getElement("barData").getElement("barTickData")
                        numvals = data.numValues()
                        print numvals
                        if numvals > 0:
                            print data.getValueAsElement(1).getElement(1).getValueAsFloat()



            if event.eventType() == blpapi.Event.SUBSCRIPTION_DATA:
                eventCount += 1
                if eventCount >= options.maxEvents:
                    break
    finally:
        # Stop the session
        session.stop()

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print "Ctrl+C pressed. Stopping..."

I have looked at the eidData and that is empty, even if I ask for it to be returned. I am looking at currencies, rather than equities, so there is no exchange entitlement required.

> (Pdb) print eid._Element__dataHolder IntradayBarResponse = {
>     barData = {
>         eidData[] = {
>         }
>         barTickData[] = {
>             barTickData = {
>                 time = 2013-08-02T18:36:00.000
>                 open = 4.233100
>                 high = 4.233600
>                 low = 4.233100
>                 close = 4.233400
>                 volume = 0
>                 numEvents = 119
>                 value = 0.000000
>             }
>             barTickData = {
>                 time = 2013-08-02T18:37:00.000
>                 open = 4.233400
>                 high = 4.233700
>                 low = 4.233100
>                 close = 4.233500
>                 volume = 0
>                 numEvents = 96
>                 value = 0.000000
>             }
>             barTickData = {
>                 time = 2013-08-02T18:38:00.000
>                 open = 4.233500
>                 high = 4.233600
>                 low = 4.233300
>                 close = 4.233500
>                 volume = 0
>                 numEvents = 135
>                 value = 0.000000
>             }
>             barTickData = {
>                 time = 2013-08-02T18:39:00.000

I am still looking for a way to associate requests with responses, without having to do the inefficient request....wait for response.... request etc. I am not sure if Bloomberg provides this functionality, however. This limitation appears to exist for historical tick data as well.

Answer

Nikolay Adrianov picture Nikolay Adrianov · Aug 3, 2013

Thomas, you should always use correlationId of a response to find which request it is associated with. IIRC, reference data and historical data requests support multiple securities, but market data and intraday bars may have only one security per request.

That is why there is additional "securityData" field in refdata and historical responses. For market data and intraday bars correlationId is enough to identify the request and hence the security.

Hope it helps.