pythonbloombergblpapi

BLPAPI. Retrieve value of specific field


I am running a subscription session using BLPAPI and I am able to get real-time data but I want to isolate a particular value from the (extensive) list of fields. Then I would like to put it into a dataframe with "Ticker" and "Field" e.g.

Ticker Last Price
ESM3 Index 4138.25
import blpapi

session = blpapi.Session()
session.start()
subscriptions = blpapi.SubscriptionList()
subscriptions.add("ESM3 Index", "LAST_PRICE", " ",)
session.subscribe(subscriptions)

while(True):
    event = session.nextEvent()
    for msg in event:
        print(msg)

It results in:

CID: {[ valueType=AUTOGEN classId=0 value=1 ]}
MarketDataEvents = {
    MKTDATA_EVENT_TYPE = TRADE
    MKTDATA_EVENT_SUBTYPE = NEW
    EVT_TRADE_DATE_RT = 2023-04-07
    NUM_TRADES_RT = 21535
    PER_TRADE_VWAP_VOLUME_RT = 59291.000000
    PER_TRADE_VWAP_TURNOVER_RT = 244947593.500000
    PER_TRADE_VWAP_REALTIME = 4131.277800
    LAST_ALL_SESSIONS = 4138.250000
    LAST2_TRADE = 4138.250000
    LAST_PRICE = 4138.250000
    LAST_PRICE_TDY = 4138.250000
    LAST2_DIR = -1
    LAST_TICK_DIRECTION_RT = 2
    LAST_TRADE = 4138.250000
    SIZE_LAST_TRADE = 2
    SIZE_LAST_TRADE_TDY = 2
    TRADE_SIZE_ALL_SESSIONS_RT = 2
    ALL_PRICE_SIZE = 2
    ALL_PRICE_COND_CODE = "TSUM"
    ALL_PRICE = 4138.250000
    VOLUME = 59598
    VOLUME_TDY = 59598
    REALTIME_VOLUME_5_DAY_INTERVAL = 
    DELTA_AVAT_1_DAY_INTERVAL = 
    DELTA_AVAT_5_DAY_INTERVAL = 
    DELTA_AVAT_10_DAY_INTERVAL = 
    DELTA_AVAT_20_DAY_INTERVAL = 
    DELTA_AVAT_30_DAY_INTERVAL = 
    DELTA_AVAT_100_DAY_INTERVAL = 
    DELTA_AVAT_180_DAY_INTERVAL = 
    LAST_PRICE_COND_CODE_RT = "TSUM"
    PRICE_CHANGE_1Y_NET_RT = -402.000000
    PRICE_CHANGE_1Y_PCT_RT = -8.854100
    LAST_CONTINUOUS_TRADE_PRICE_RT = 4138.250000
    PRICE_LAST_RT = 4138.250000
    LAST_TRADE_PRICE_TODAY_RT = 4138.250000
    EVT_TRADE_PRICE_RT = 4138.250000
    EVT_TRADE_SIZE_RT = 2
    EVT_TRADE_CONDITION_CODE_RT = "TSUM"

I would like to be able to extract a specific ticker e.g. "LAST_PRICE"

I have tried using msg.getElement("LAST_PRICE") but it doesn't like this as it says the sub-element cannot be found.


Solution

  • Expanding on the code similar to nature as @DS_London's but incorporating your need for the data to be in a data frame. Although not the most efficient code as highlighted by my need for this post thought it could nevertheless be valuable and will update at such as time I improve on it.

    import blpapi
    import pandas as pd
    import numpy as np
    import os
    
    # initialise bloomberg
    host='localhost'
    port=8194
    
    session_options = blpapi.SessionOptions()
    session_options.setServerHost(host)
    session_options.setServerPort(port)
    session_options.setSlowConsumerWarningHiWaterMark(0.05)
    session_options.setSlowConsumerWarningLoWaterMark(0.02)
    
    session = blpapi.Session(session_options)
    if not session.start():
        print("Failed to start Bloomberg session.")
        
    session.start()
    subscriptions = blpapi.SubscriptionList()
    
    # sample selection of securities and fields
    fields = ['BID','ASK','TRADE','LAST_PRICE']
    subscriptions.add('VOD LN Equity', fields, "", blpapi.CorrelationId('VOD LN Equity'))
    subscriptions.add('AZN LN Equity', fields, "", blpapi.CorrelationId('AZN LN Equity'))
    
    session.subscribe(subscriptions)
    
    ColPosDict = {'BID':0,
                  'ASK':1,
                  'TRADE':2,
                  'LAST_PRICE':3}
    
    RowPosDict = {'VOD LN Equity':0,
                  'AZN LN Equity':1}
    
    df_AllData = pd.DataFrame(np.nan, index=list(['VOD LN Equity' ,'AZN LN Equity']), columns= fields)
    
    while(True):
        event = session.nextEvent()
        if event.eventType() == blpapi.Event.SUBSCRIPTION_DATA: 
            for msg in event:
                security = msg.correlationIds()[0].value()
                eltMsg = msg.asElement()
                for fld in fields:
                    if eltMsg.hasElement(fld):
                        df_AllData.iat[RowPosDict[security], ColPosDict[fld]] = eltMsg.getElement(fld).getValueAsFloat() 
            os.system('cls' if os.name == 'nt' else 'clear')
            print(df_AllData)
    

    Example Output:

                        BID       ASK  TRADE  LAST_PRICE
    VOD LN Equity     69.72     69.76    NaN       69.72
    AZN LN Equity  11200.00  11204.00    NaN    11200.00
    
    

    Comment:

    In this code, the DataFrame is stored in memory, so other parts of the program can access it without refetching the data. To utilise this, you could create a class that handles:

    •   Connecting to Bloomberg.
    •   Subscribing to securities.
    •   Retrieving data when updates come in.
    

    Using PyQt signals (or other signal-slot mechanisms), you can trigger data retrieval when Bloomberg sends new data, rather than continuously polling. This approach avoids unnecessary data usage, especially for tickers that update infrequently (e.g., once a day).

    Subscription data gets added to a “queue” from which you receive the data. Bloomberg sends YOU the data you don’t fetch it in a subscription.