DesktopDeveloperAPIcoreDevguide (BLAPI)
DesktopDeveloperAPIcoreDevguide (BLAPI)
5
Last Updated: 7/18/2016
BLOOMBERG OPEN API – CORE DEVELOPER GUIDE
RELATED DOCUMENTS
DOCUMENT NAME
All materials including all software, equipment and documentation made available by Bloomberg are for informational purposes only. Bloomberg and its
affiliates make no guarantee as to the adequacy, correctness or completeness of, and do not make any representation or warranty (whether express or
implied) or accept any liability with respect to, these materials. No right, title or interest is granted in or to these materials and you agree at all times to
treat these materials in a confidential manner. All materials and services provided to you by Bloomberg are governed by the terms of any applicable
Bloomberg Agreement(s).
Contents
Contents
Contents .................................................................................................................................................................................. 3
1. About This Guide............................................................................................................................................................. 6
1.1. Overview ................................................................................................................................................................. 6
1.1.1. API Features ................................................................................................................................................... 6
1.1.2. Bloomberg Product Features .......................................................................................................................... 7
2. Subscription Overview .................................................................................................................................................... 9
2.1. Subscription Life Cycle ............................................................................................................................................ 9
2.2. Starting a Subscription .......................................................................................................................................... 10
2.3. Building a Subscription .......................................................................................................................................... 13
2.4. Example of Building a Subscription....................................................................................................................... 13
2.5. Subscription Method ............................................................................................................................................. 15
2.6. Subscription Status Messages .............................................................................................................................. 15
2.7. Subscription Data Messages ................................................................................................................................ 18
2.8. Subscription Errors/Exceptions ............................................................................................................................. 21
2.9. Modifying an Existing Subscription ....................................................................................................................... 22
2.10. Stopping a Subscription ........................................................................................................................................ 23
2.11. Overlapping Subscriptions .................................................................................................................................... 23
2.12. Receiving Data from a Subscription ...................................................................................................................... 24
2.13. Snapshot Requests for Subscriptions ................................................................................................................... 25
3. Subscription Classes ..................................................................................................................................................... 25
3.1. SessionOptions Class ........................................................................................................................................... 26
3.2. Session Class........................................................................................................................................................ 26
3.3. Establishing a Connection ..................................................................................................................................... 27
4. Data Requests............................................................................................................................................................... 29
5. Bloomberg Services ...................................................................................................................................................... 30
5.1. Service Schemas .................................................................................................................................................. 30
5.2. Accessing a Service .............................................................................................................................................. 31
5.3. Market Data Service .............................................................................................................................................. 32
5.4. Reference Data Service ........................................................................................................................................ 34
5.4.1. Requesting Reference Data .......................................................................................................................... 34
5.4.2. Handling Reference Data Messages ............................................................................................................ 35
5.4.3. Handling Reference Data (Bulk) Messages .................................................................................................. 37
5.5. Source Reference Service .................................................................................................................................... 38
5.6. Custom VWAP Service ......................................................................................................................................... 40
5.7. Market Depth Data Service ................................................................................................................................... 40
1.1. OVERVIEW
All API products share the same programming interface and behave almost identically. The main difference is that
customer applications using the enterprise API products (which exclude the Desktop API) have some additional
responsibilities, such as performing authentication, authorization and permissioning before distributing/receiving data.
THREAD-SAFETY
The interface is thread safe and thread aware, giving applications the ability to utilize multiple processors efficiently.
32- AND 64-BIT PROGRAMMING SUPPORT
The Java and .NET API work on both 32- and 64-bit platforms, while the C/C++ API libraries are currently available in
both 32- and 64-bit versions.
PURE JAVA IMPLEMENTATION
The Java API is implemented entirely in Java. Bloomberg did not use JNI to wrap either the existing C library or the new
C++ library.
FULLY INTROSPECTIVE DATA MODEL
An application can discover a service and its attributes at runtime.
BANDWIDTH OPTIMIZED
The Bloomberg API automatically breaks large results into smaller chunks and can provide conflated streaming data to
improve the bandwidth usage and the latency of applications.
THE THREE PARADIGMS
Before exploring the details for requesting and receiving data, the following three paradigms used by the Bloomberg API
are described:
Request/Response
Subscription
Publishing
Note: Applications that make heavy use of real-time market data should use the streaming real-time market data
service. However, real-time information is available through the reference data service requests, which include the
current value in the response.
2. Subscription Overview
Subscriptions are ideal for data that changes frequently and/or at unpredictable intervals. Instead of repeatedly polling for
the current value, the application gets the latest value as soon as it is available without spending time and bandwidth if
there have been no changes. This module contains more details on how to start, modify and stop subscriptions as well as
what to expect as the result of a subscription and how to handle those results.
Currently, the subscription-based Bloomberg API core services are market data (//blp/mktdata), market bar (//blp/mktbar)
and Custom VWAP (//blp/mktvwap). Some subscription-based services are only available for B-PIPE users, such as
market depth, market list and source reference data. In the future, the Bloomberg API may support delivering information
other than market data through a subscription service.
This section offers a demonstration of how to subscribe to streaming data and handle its data responses.
Following are the basic steps to subscribe to market data:
1. Establish a connection to the product’s communication server using the Session.Start method.
2. Open the “//blp/mktdata” service using the Session.OpenService method.
3. Build the subscription. For C/C++ API or Java API: Create a SubscriptionList object, which is a list of subscriptions
used when subscribing and unsubscribing. Using its add method, add one security, along with one or more fields,
desired options (e.g., Interval, Delayed) and a correlation identifier. For .NET API: Declare and instantiate a Generic
List variable of Subscriptions and then add a new Subscription object to it for each subscription.
4. Submit the SubscriptionList or Generic List variable using the Session.subscribe method.
5. Handle the data and status responses, either synchronously or asynchronously, which are then returned as Events.
An Event containing data will be identified by an Event type of SUBSCRIPTION_DATA, while a status Message will
be of type SUBSCRIPTION_STATUS.
The topic. In the case of “//blp/mktdata,” the topic value consists of an optional symbology identifier followed by
an instrument identifier. For example, “/cusip/ 097023105” and “/sedol1/2108601” include the symbology
identifier, whereas “IBM US Equity” omits the symbology identifier. If users do not specify the symbology identifier,
then the defaultTopicPrefix of the SessionOptions object is used.
Note: The topic’s form may be different for different subscription services.
The options. These are qualifiers that can affect the content delivered. Examples in “//blp/mktdata” include
specifying an interval for conflated data.
The correlation ID. Data for each subscription is tagged with a correlation ID (represented as a CorrelationID object)
that must be unique to the Session. The customer application can specify that value when the subscription is created.
If the customer application does not specify a correlation ID, the Bloomberg infrastructure will supply a suitable value;
however, in practice, the internally generated correlation ID is rarely used. Most customer applications assign
meaningful correlation IDs that allow the mapping of incoming data to the originating request or subscription.
A user can represent any subscription as a single string that includes the service name, topic and options. For example:
“//blp/mktdata/cusip/097023105?fields=LAST_PRICE,LAST_TRADE_ACTUAL” represents a subscription
using the market data service to an instrument (BA) specified by CUSIP where any changes to the fields
LAST_PRICE or LAST_TRADE_ACTUAL from the Bloomberg data model should generate an update.
The Bloomberg API provides methods that accept the subscription specification as a single string as well as methods that
specify the different elements of the subscription as separate parameters. Subscriptions are typically manipulated in
groups, so the Bloomberg API provides methods that operate on a list of subscriptions. This example shows subscription
creation by several of these methods.
……
SubscriptionList subscriptions = new
SubscriptionList(); CorrelationID subscriptionID_IBM =
new CorrelationId(10); subscriptions.add(new
Subscription("IBM US Equity",
"LAST_TRADE",
subscriptionID_IBM)));
subscriptions.add(new Subscription("/ticker/GOOG US Equity",
"BID,ASK,LAST_PRICE",
new CorrelationID(20)));
subscriptions.add(new Subscription("MSFT US Equity",
"LAST_PRICE",
"interval=.5",
new CorrelationID(30)));
subscriptions.add(new Subscription(
"/cusip/097023105?fields=LAST_PRICE&interval=5.0", //BA US
Equity new CorrelationID(40)));
session.subscribe(subscriptions);
………
Subscribing to this list of subscriptions returns an Event of type SUBSCRIPTION_STATUS consisting of a Message
object of type SubscriptionStarted for each CorrelationID. For example, the user-defined “dump” method used in previous
examples shows:
eventType=SUBSCRIPTION_STATUS messageType=SubscriptionStarted
CorrelationID=User: 10 SubscriptionStarted = {
}
messageType=SubscriptionStarted CorrelationID=User: 20 SubscriptionStarted =
{
}
messageType=SubscriptionStarted CorrelationID=User: 30 SubscriptionStarted =
{
}
messageType=SubscriptionStarted CorrelationID=User: 40 SubscriptionStarted =
{
}
In case of an error, an Event is available to report the subscriptions that failed. For example, if the specification for MSFT
(CorrelationID 30) above was mistyped (MSFTT),that would result in the following Event:
eventType=SUBSCRIPTION_STATUS
messageType=SubscriptionFailure
CorrelationID=User: 30
SubscriptionFailure = {
reason = {
source =
BBDB@p111
errorCode = 2
category =
BAD_SEC
• Topic: In the case of “//blp/mktdata,” the topic value consists of an optional topic prefix followed by an instrument
identifier. For example, “/cusip/097023105” and “/sedol1/2108601” include the topic prefix, whereas “IBM US
Equity” omits the topic prefix. If the topic prefix is not specified, the defaultTopicPrefix of the SessionOptions object is
used, which is “/ticker” by default. Therefore, if using a ticker, such as IBM, the security string would be “IBM US
Equity,” with the “/ticker” topic prefix is implied. Note: The topic’s form may be different for different subscription
services.
• Fields: API fields define the type of data to retrieve for the specified topic. These are required, comma-delimited and
are prefixed with a question mark immediately following the topic. Make sure that the fields being used are real-time
fields, indicated by white text on {FLDS <GO>} on the Bloomberg Professional® service. Otherwise, an invalid field
error within the response for that security’s subscription will be returned.
• Options: These are optional qualifiers that can affect the content delivered. Examples for
“//blp/mktdata” include specifying an interval for conflated data (i.e., interval=n, where n is measured in seconds) or
indicating receipt of delayed data, which is accomplished via the “delayed” option. They are prefixed by an ampersand
(&). If using the “//blp/mktvwap” service, specify one or more override field/value pairings. If using the Desktop API,
the “useGMT” option can be used—that will ensure that all time data being returned is converted to GMT/UTC. This
option is available only for the Desktop API because the streaming data is initially being adjusted based on the
Bloomberg Professional service’s {TZDF <GO>} settings. All other products will default to receiving time-specific
streaming data in GMT/UTC (unadjusted).
• Correlation ID (optional): Data for each subscription is tagged with a correlation ID, represented as a CorrelationID
object, that must be unique to the session. The customer application can specify that value when the subscription is
created. If the customer application does not specify a correlation ID, the Bloomberg infrastructure will supply a
suitable value. In practice, the internally generated correlation ID is rarely used. Most customer applications assign
meaningful correlation IDs that allow the mapping of incoming data to the originating request or subscription.
As an alternative to representing a subscription as a single string that includes the service name, topic, fields and options,
the subscription string can be broken down into separate parameters. In the following example, subscriptions are created
using both methods:
<C++>
public void processEvent(Event event, Session session) {
switch (event.eventType())
{
case Event::SERVICE_STATUS: {
<C++>
Case Event::SESSION_STATUS: {
MessageIterator iter = event.messageIterator();
while (iter.hasNext()) {
Message message = iter.next();
if (message.messageType().equals("SessionStarted")) {
try {
session.openServiceAsync("//blp/mktdata",
CorrelationID(99));
} catch (Exception &e) {
std::cerr << "Could not open //blp/mktdata for async";
std::exit(-1);
}
} else {
// Handle error.
}
}
break;
}
On receipt of a SERVICE_STATUS type Event, the Messages are searched for one indicating that the openServiceAsync
call was successful. The Message type must be “ServiceOpened” and the correlation ID must match the value assigned
when the request was sent.
If the service was successfully opened, users can create, initialize and send a request. The only difference is that the call
to subscribe must be guarded against the transmission of exceptions—not a concern until now.
<C++>
public void processEvent(Event event, Session session) {
switch (event.eventType())
{
case Event::SERVICE_STATUS: {
// If service opened successfully, send request.
break;
}
case Event::SUBSCRIPTION_STATUS: {
// If subscription fails, then perform appropriate action
break;
}
case Event::AUTHORIZATION_REQUEST:
// If authorization was successful, perform next action.
break;
}
default: {
// Handle unexpected response.
break;
}
}
eventType=SUBSCRIPTION_DATA
messageType=MarketDataEvents
CorrelationID=User: 10
MarketDataEvents = {
LAST_PRICE = 212.64
BID = 212.63
ASK = 212.64
MKTDATA_EVENT_TYPE = SUMMARY
MKTDATA_EVENT_SUBTYPE = INITPAINT
IS_DELAYED_STREAM = false
…
In the above output, the Event type is “SUBSCRIPTION_DATA”. This is the Event type handled in the code.
The next step would be taking a deeper look into a subscription-based data event handler. Displayed below is the partial
code sample that handles those particular subscription Messages. The handleOtherEvent function definition has been
removed for brevity.
<C++>
#include <blpapi_correlationid.h>
#include <blpapi_event.h>
#include <blpapi_message.h>
#include <blpapi_request.h>
#include <blpapi_session.h>
#include <blpapi_subscriptionlist.h>
#include <iostream>
using namespace BloombergLP;
using namespace blpapi;
static void handleDataEvent(const Event& event, int updateCount)
{
std::cout << "EventType=" << event.eventType() << std::endl;
std::cout << "updateCount = " << updateCount << std::endl;
MessageIterator iter(event);
while (iter.next()) {
Message message = iter.message();
std::cout << "correlationId = " << message.correlationId() <<
std::endl;
std::cout << "messageType = " << message.messageType() << std::endl;
message.print(std::cout);
}
}
int main(int argc, char **argv)
{
SessionOptions sessionOptions;
sessionOptions.setServerHost("localhost");
sessionOptions.setServerPort(8194);
Session session(sessionOptions);
if (!session.start()) {
std::cerr <<"Failed to start session." << std::endl;
return 1;
}
if (!session.openService("//blp/mktdata")) {
std::cerr <<"Failed to open //blp/mktdata" << std::endl;
return 1;
}
CorrelationId subscriptionId((long long)2);
SubscriptionList subscriptions;
subscriptions.add("AAPL US Equity", "LAST_PRICE", "", subscriptionId);
session.subscribe(subscriptions);
int updateCount = 0;
while (true) {
Event event = session.nextEvent();
switch (event.eventType()) {
case Event::SUBSCRIPTION_DATA:
handleDataEvent(event, updateCount++);
break;
default:
handleOtherEvent(event); // This function, if shown,
// would handle Status messages,
// such as session terminated,
// and so forth
break;
}
}
return 0;
}
In the previous code sample, it is important to observe the following:
The tick data from the subscribe call is being handled in synchronous mode. This is determined by the combination of
the nextEvent call and the fact that no EventHandler is being provided to the Session object when it is being created.
Remember that if nextEvent is called when an EventHandler is provided, then an exception will be thrown.
When the Event type is Event::SUBSCRIPTION_DATA, the handleDataEvent method is then called where a
MessageIterator is created and used to iterate over the Message objects within the Event.
The Event type and counter are then printed and, for each tick update, the correlation ID, Message type and tick data
dump are also sent to std::cout.
The correlation ID in this case will be the value of the subscriptionId variable that was sent with the subscription. In an
application with more than the one security being subscribed, assign a different correlation id to each SubscriptionList
item and use them to map the tick update to the actual subscription that was sent.
Not displayed in this code snippet is the handleOtherEvent method code.
<C++>
if (msg.hasElement(“reason”)) {
Element reason = msg.getElement(“reason”);
fprintf(stdout, " %s: %s\n",
reason.getElement(“category”).getValueAsString(),
reason.getElement(“description”).getValueAsString());
}
Following is a sample printout of a “reason” Message that includes the category and description:
SubscriptionFailure = {
reason = {
category = BAD_SEC
description = Invalid security
}
}
Following is sample code that demonstrates how to handle an “exceptions” Message type:
<C++>
if (msg.hasElement(“exceptions”)) {
Element exceptions = msg.getElement(“exceptions”);
for (size_t i = 0; i < exceptions.numValues(); ++i) {
Element exInfo = exceptions.getValueAsElement(i);
Element fieldId = exInfo.getElement(“fieldId”);
Element reason = exInfo.getElement(“reason”);
fprintf(stdout, " %s: %s\n",
fieldId.getValueAsString(),
reason.getElement(“category”).getValueAsString());
}
}
Note: Use of the resubscribe method is generally preferred to cancelling the subscription (unsubscribe
method) and creating a new subscription because updates might be missed between the unsubscribe and
subscribe calls.
The resubscribe method accepts a SubscriptionList. For example, let’s say that users initially subscribed to “IBM US
Equity” along with LAST_PRICE and BID, passing subscriptionID_IBM as the correlation identifier. This would look
like the following:
If users would like to modify that subscription and remove the LAST_PRICE field, retain the BID field and add the ASK
field, the following code fragment can be used:
Note: The client receives an Event object indicating successful resubscription (or not) before receipt of any
data from that subscription. Also, the behavior is undefined if the topic of the subscription (e.g., the security
itself) is changed.
If the allowMultipeCorrelatorsPerMsg option is false (the default), then a Message object that matches more than one
subscription will be returned multiple times from the MessageIterator, each time with a single, different CorrelationID.
If the allowMultipleCorrelatorsPerMsg object is true, then a Message object that matches more than one subscription will
be returned just once from the MessageIterator. The customer application developer must supply logic to examine the
multiple CorrelationID values (see the numCorrelationIds and correlationIDAt methods of the Message class) and
dispatch the appropriate data to the correct application software.
IND_BID_FLAG = false
IND_ASK_FLAG = false
IS_DELAYED_STREAM = true
TIME =
14:34:44.000+00:00
VOLUME = 7589155
RT_OPEN_INTEREST = 8339549
RT_PX_CHG_PCT_1D = -0.32
VOLUME_TDY = 7589155
LAST_PRICE = 118.15
HIGH = 118.7
LOW = 116.6
LAST_TRADE = 118.15
OPEN = 117.5
PREV_SES_LAST_PRICE
P = 118.53
EQY_TURNOVER_REALTIME
R = 8.93027456E8
RT_PX_CHG_NET_1D
E = -0.379999
V
OPEN_TDY = 117.5
_
S
LAST_PRICE_TDY = 118.15
E
HIGH_TDY
S = 118.7
_
LOW_TDY = 116.6
L
RT_API_MACHINE = p240
A
S
T
_
P
©2016 BLOOMBERG L.P. ALL RIGHTS RESERVED 24
R
I
C
BLOOMBERG OPEN API – CORE DEVELOPER GUIDE
API_MACHINE = p240
RT_PRICING_SOURCE =
US EXCH_CODE_LAST = D
EXCH_CODE_BID = O
SES_START = 09:30:00.000+00:00
SES_END = 16:30:00.000+00:00
}
std::vector<RequestTemplate> snapshots;
std::string subscriptionString(d_service + d_topic + fieldsStr);
snapshots.push_back(session.createSnapshotRequestTemplate(
subscriptionString.c_str(),
CorrelationId(d_topic),
subscriptionIdentity));
3. Subscription Classes
Before delving deeper into the various classes and class members available via the API libraries, it is important to have a
high-level understanding of the typical structure of a Bloomberg API application and how it may differ depending upon the
product used. This module will describe the core components that make up a typical Bloomberg API application.
The two API classes that are responsible for both connecting users application to their Bloomberg API product’s
communication server process and performing the necessary authentication, authorization and data request duties are
SessionOptions and Session, which will be covered next.
Important methods of the Session class that are used by all API products include:
START
This establishes a connection with the product’s communication server process. It issues a blocking call to start the
Session.
STOP
This stops the operation of the Session.
OPENSERVICE
It opens the service having the specified URI (e.g., “//blp/refdata”, “//blp/mktdata”, etc).
GETSERVICE
This service returns a handle to a Bloomberglp.Blpapi.Service object representing the service identified by the specified
URI. This method is not used for a subscription-based request (e.g., “//blp/mktdata”).
SENDREQUEST
This sends a completed request to the service, including “//blp/refdata”, “//blp/apiflds” and “//blp/tasvc”.
SUBSCRIBE
This sends a subscription list to be subscribed. It is used for services such as “//blp/mktdata”, “//blp/mktvwap”,
and “//blp/mktbar”.
RESUBSCRIBE
Modifies each subscription in the specified SubscriptionList (for C++ API and Java) or generic List<Subscription> (for Java
API and .NET API) to reflect the modified options specified.
UNSUBSCRIBE
Cancels previous requests for asynchronous topic updates associated with the CorrelationIDs listed in the specified
SubscriptionList (for C++ API and Java) or generic List<Subscription> (for Java API and .NET API).
CREATESNAPSHOTREQUESTTEMPLATE
Creates template to be used for snapshot subscription requests.
CANCEL
Cancels outstanding subscriptions, templates or requests represented by the specified CorrelationIDs or generic
List<CorrelationID>.
Following are a few of the important methods of the Session class needed by the enterprise API products (Server API,
Platform and B-PIPE):
GENERATETOKEN
Requests a token string for the specified application and/or user entered in EMRS, which is then used for authorization.
SENDAUTHORIZATIONREQUEST
Sends a completed authorization request to the authorization service (“//blp/apiauth”).
CREATEIDENTITY
Returns an identity that is valid but not authorized.
uncommon to find a Desktop API application that does not use this class object for this reason, but may call its other class
members.
This is not the case for the enterprise API products, which will require that at least one of these two properties be set or
possibly not used at all. In place of those two properties, an enterprise application wishing to handle failover situations
would use the ServerAddresses and AutoRestartOnDisconnection members of the SessionOptions class. If the
connection is lost to the primary host/server, the application will connect to the next pairing specified by the
ServerAddresses property. To use this property, the AutoRestartOnDisconnection property must be set to true (default is
false). Failover will be covered in detail within the Enterprise documentation.
In an Enterprise application that is not handling failover, the ServerHost and ServerPort properties will be set. For
instance, if the serverapi process was installed on a Windows, Solaris or Linux box with the defaults, it will most likely be
listening on port 8194, which is the default of the SessionOptions.ServerPort property as previously mentioned. Since the
server process is probably not installed on the same machine as the application (unless possibly testing on a
development machine), the SessionOptions.ServerHost property will not be the default “localhost” value.
Once the required properties are set, the SessionOptions object will be used when instantiating the Session object. The
settings will take effect when the Session.Start method is called on to establish a connection between the application and
the communication server process.
4. Data Requests
STREAMING DATA (MARKET DATA)
Real-time and/or delayed streaming tick data is retrieved by subscribing to or monitoring a list of securities and real-time
fields. Once a subscription is made, continuous or intervalized tick updates will be sent from the Bloomberg Data Center
until the user cancels or unsubscribes from that subscription. The Subscribe method will be used.
PER REQUEST DATA (REFERENCE DATA / BULK DATA)
Data retrieved by sending a Request object via the SendRequest method. Per request data comprises of values for the
requested securities/fields at that moment in time, assuming the user has real-time entitlements to that data. Otherwise,
delayed values will be received. Static fields (e.g., PX_LAST instead of LAST_PRICE, where the latter is a real-time field)
should be used. However, real-time fields will also work in this type of request as each has an equivalent static field.
Bulk data is also a of data, but it is represented by more than one piece of data and requires special handling. For
instance, “COMPANY_ADDRESS” is a bulk field and returns multiple lines of information. Bulk fields are identified on
{FLDS <GO>} by the “Show Bulk Data…” text in its Value column. For both types of data, a Request object of type
“ReferenceDataRequest” is created.
This can be tested by loading “IBM US Equity” on the Bloomberg Professional service, running {FLDS <GO>} in the same
window and entering “company address” in the yellow query field below the security and pressing {<GO>}.
HISTORICAL DATA
Data represented by a single point of data for each day specified in the date range of the historical request. Use the
SendRequest method to make this request. A Request object of type “HistoricalDataRequest” will be created. Before
submitting the Request object to Bloomberg, add any securities and (historical) fields, a start and end date range, and set
any applicable elements to customize the request. For instance, to only receive data for trading days or data for all
calendar days, fill in the non-trading days with the previous trading day’s value.
INTRADAY DATA
Data available as:
Tick data — Each tick over a defined period of time
Bar data — A series of intraday summaries over a defined period of time for a security and Event type pair
In both cases, pass the request using the SendRequest method, but only specify one security for each
Request object submitted. For intraday ticks, create an object of type “IntradayTickRequest.” For bars, create an object of
type “IntradayBarRequest.”
5. Bloomberg Services
There are two Core service schemas and several additional services that are common to all or some of the API products.
SERVICES
1. Market Data — //blp/mktdata: Used when subscribing to streaming real-time and delayed market data.
2. Reference Data — //blp/refdata: Used when requesting reference data such as pricing, historical/time-series and
intraday bars and ticks.
3. Source Reference — //blp/srcref: Used to subscribe to the source reference and tick-size data available for the
specified entitlement ID.
4. Vwap — //blp/mktvwap: Subscription-based service used when requesting streaming custom Volume-Weighted-
Average-Price data.
5. Market Depth (B-PIPE ONLY) — //blp/mktdepthdata: Market Depth Data service.
6. Market Bar — //blp/mktbar: Subscription-based service used when requesting streaming real-time intraday market
bar data. This service is currently unavailable to B-PIPE users.
7. Market List — //blp/mktlist: Used to perform two types of list data operations. The first is to subscribe to lists of
instruments, known as “chains,” using the “chain” <subservice name> (i.e., //blp/mktlist/chain). The second is to request a
list of all the instruments that match a given topic key using the “secids” <subservice name> (i.e., //blp/mktlist/secids). The
//blp/mktlist service is available to both BPS (Bloomberg Professional service) and NONBPS users.
8. API Fields — //blp/apiflds: Used to perform queries on the API Field Dictionary. It provides functionality similar to
{FLDS <GO>}.
9. Instruments — //blp/instruments: The Instruments service is used to perform three types of operations. The first is
a Security Lookup Request, the second is a Curve Lookup Request and the third is a Government Lookup Request.
10. Page Data — //blp/pagedata: Subscription-based service providing access to GPGX pages and the data they
contain. The GPGX number, the monitor number, the page number and the required rows (fields) must be provided.
11. Technical Analysis — //blp/tasvc: The Technical Analysis service downloads data and brings it into an application
using Bloomberg API.
12. Curves Toolkit — //blp/irdctk3: The CTK (Curves Toolkit) service allows users to interact with interest rate curves
directly and retrieve the data available on the ICVS <GO> function.
Optional Field 0 1
Required Field 1 1
Array 1 –1
“//namespace/service”; (for example, “//blp/refdata” for reference data or “//blp/apiauth” for authorization
functions)
Once a service has been successfully opened, it remains available for the lifetime of that Session object.
Important Note: When making a subscription-based request (via “//blp/mktdata”, “//blp/mktvwap”, or other
subscription-based services), the getService method is not used.
Building upon the code from the establishing a connection section, following is an example of how these service-related
methods might be used.
<C++>
int main()
{
SessionOptions sessionOptions;
sessionOptions.setServerHost("10.10.10.10"); // Or specify machine name
sessionOptions.setServerPort(8194);
//Establish Session
Session session(sessionOptions);
//Attempt to Start Session
if (!session.start()) {
std::cerr <<"Failed to start session." << std::endl;
return 1;
}
//Attempt to open reference data service
if (!session.openService(“//blp/refdata”))
{
std::cerr << "Failed to open //blp/refdata service" << std::endl;
return 1;
}
Service authorizationService = session.getService(“//blp/refdata”);
}
In the above code, an attempt is made to open the “//blp/refdata” service and then, if successful, the user can call
the getService method to obtain a Service object that will then be used when creating the request object.
<C++>
// Assume that session already exists and the "//blp/mktdata" service has
// been successfully opened.
SubscriptionList subscriptions;
subscriptions.add("IBM US Equity",
"LAST_PRICE,BID,ASK",
"");
subscriptions.add("/cusip/912828GM6@BGN",
LAST_PRICE,BID,ASK,BID_YIELD,ASK_YIELD",
"");
session.susbcribe(subscriptions);
Some of the fields that are returned also have a null state. For example, the fields BID and ASK have values of type float
and usually give positive values that can be used to populate a user’s own caches. However, at times these fields will be
set to a null value. For BID and ASK fields, this is usually interpreted as an instruction to clear the values in the caches. It
is important to test to see if the field is null before trying to retrieve a value from it.
MARKET DATA EVENT TYPES AND SUB-TYPES
There are a number of possible market data Event types and sub-types that a subscription-based application is expected
to handle. When subscribing to market data for a security, the API performs two actions:
• Retrieves and delivers a summary of the current state of the security. A summary consists of data elements
known as ”fields”. The set of summary fields varies depending on the asset class of the requested security.
• The API streams all market data updates as they occur until subscription cancellation. About 300 market data
fields are available via the API subscription interface, most of them derived from trade and quote Events.
An Event of type SUBSCRIPTION_DATA will contain a MessageType of “MarketDataEvents” that contains any of the
following market data Event types (i.e., MKTDATA_EVENT_TYPE):
SUMMARY
This market data Event type Message can be any of the following market event sub-types
(MKTDATA_EVENT_SUBTYPE):
INITPAINT — Message is the initial paint, which comprises the most recent value for all the fields specified in the
subscription as well as possibly other fields that were not included in the subscription. The inclusion of these extra
fields is done to enhance performance on the Bloomberg. If the subscription is interval-based (i.e., an interval of n >
0), only SUMMARY INITPAINT Messages will be received every n number of seconds as the header is basically sent
at the interval points with the latest tick values.
INTRADAY — Message indicates a regular summary Message, usually sent near the beginning of a zero-interval-
based subscription (closely after the INITPAINT SUMMARY messages). It is an update to the INITPAINT Message.
NEWDAY — Sent from the Bloomberg Data Center to indicate that a new market day has occurred for the particular
instrument subscribed to. It is sent after the market has closed and before the market opens the next day. Many times
the first occurrence of this tick will be received an hour or two after market close. It is possible to receive more than
one such tick between the market close and market open. This is the time where certain fields are re-initialized to
zero, including VOLUME (the total number of securities traded in that day), to prepare for the new day.
INTERVAL — Returned only when making an interval-based subscription. All messages will be of this type/sub-type.
An INITPAINT Message or any QUOTE- or TRADE-type Messages will not be received.
DATALOSS — Indicates that data has been lost. The library drops Events when the number of Events outstanding for
delivery exceeds the specified threshold controlled by SessionOptions.maxEventQueueSize. The correlationID
property attached to the DATALOSS Message identifies the affected subscription.
TRADE
This market data Event type indicates that this Event contains a trade Message and can be any of the following market
data sub-types (MKTDATA_EVENT_SUBTYPE):
NEW — Message contains a regular trade tick.
CANCEL — Message contains a cancellation of a trade.
CORRECTION — Message contains a correction to a trade.
QUOTE
This market data Event type Message can be any one of the following market Event sub-types
(MKTDATA_EVENT_SUBTYPE):
BID —Single BID-type field inside, along with its applicable value.
ASK — Single ASK-type field inside, along with its applicable value.
MID — Single MID-type field inside, along with its applicable value.
PAIRED — Both single ASK- and BID-type fields inside, along with their applicable values (available only for the B-
PIPE product).
For additional information, refer to the “Reference Services and Schemas Guide.”
Note: Although other types of data are available under the //blp/refdata service, the aforementioned types
are the most common and will serve as the primary focus of this module.
<C++>
// Assume that the //blp/refdata service has already been opened
Service refDataService = session.getService("//blp/refdata");
Request request = refDataService.createRequest("ReferenceDataRequest");
request.append("securities", "IBM US Equity");
request.append("securities", "/cusip/912828GM6@BGN");
request.append("fields", "PX_LAST");
request.append("fields", "DS002");
session.sendRequest(request, null);
Bulk fields and/or overrides can also be included in the request. Due to the array-like format of a bulk field, they are
processed a little differently. This is covered later in the guide.
MessageIterator msgIter(event);
while (msgIter.next()) {
Message msg = msgIter.message();
Element securities = msg.getElement(SECURITY_DATA);
size_t numSecurities = securities.numValues();
std::cout << "Processing " << (unsigned int)numSecurities
<< " securities:"<< std::endl;
for (size_t i = 0; i < numSecurities; ++i) {
Element security = securities.getValueAsElement(i);
std::string ticker = security.getElementAsString(SECURITY);
std::cout << "\nTicker: " + ticker << std::endl;
if (security.hasElement("securityError")) {
printErrorInfo("\tSECURITY FAILED: ",
security.getElement(SECURITY_ERROR));
continue;
}
if (security.hasElement(FIELD_DATA)) {
const Element fields = security.getElement(FIELD_DATA);
if (fields.numElements() > 0) {
std::cout << "FIELD\t\tVALUE"<<std::endl;
std::cout << "-----\t\t-----"<< std::endl;
size_t numElements = fields.numElements();
for (size_t j = 0; j < numElements; ++j) {
Element field = fields.getElement(j);
std::cout << field.name() << "\t\t" <<
field.getValueAsString() << std::endl;
}
}
}
std::cout << std::endl;
}
}
}
where <topic> is comprised of <topic type>/<topic key>. Table below provides further details.
SOURCE REFERENCE STRING DEFINITIONS
<service owner> For B-PIPE is “blp”
<service name> Source Reference and Tick Size subscription service name is “ /srcref”
<subservice name> /brokercodes, /conditioncodes, /tradingstatuses or /ticksizes
SUBSERVICE DEFINITIONS
Subservice Subscription String Format Description
/brokercodes //blp/srcref/brokercodes/eid/<eid> List of all possible Broker codes for a specified EID
/conditioncodes //blp/srcref/conditioncodes/eid/<eid> List of Market Depth, Quote and Trade Condition codes for a
specified EID
/tradingstatuses //blp/srcref/tradingstatuses/eid/<eid> List of trading statuses and trading periods for a specified
EID
/ticksizes //blp/srcref/ticksizes/eid/<eid> List of Tick Sizes for a specified EID
Filters can be used for /conditioncodes and /tradingstatuses subscription only. Here are the possible filters available for
each:
FILTERS FOR EVENTS
Filter Name (type) Subscription String Format
Subservice Name: /conditioncodes
TRADE //blp/srcref/conditioncodes/eid/<eid>?type=TRADE
QUOTE //blp/srcref/conditioncodes/eid/<eid>?type=QUOTE
MKTDEPTH //blp/srcref/conditioncodes/eid/<eid>?type=MKTDEPTH
TRADE,QUOTE //blp/srcref/conditioncodes/eid/<eid>?type=TRADE,QUOTE
TRADE,MKTDEPTH //blp/srcref/conditioncodes/eid/<eid>?type=TRADE,MKTDEPTH
QUOTE,MKTDEPTH //blp/srcref/conditioncodes/eid/<eid>?type=QUOTE,MKTDEPTH
TRADE,QUOTE,MKTDEPTH //blp/srcref/conditioncodes/eid/<eid>?type=TRADE,QUOTE,MKTDEPTH
Subservice Name: /tradingstatuses
PERIOD //blp/srcref/tradingstatuses/eid/<eid>?type=PERIOD
STATUS //blp/srcref/tradingstatuses/eid/<eid>?type=STATUS
PERIOD,STATUS //blp/srcref/tradingstatuses/eid/<eid>?type=PERIOD,STATUS
For subscriptions without a filter, users will receive all Event types of that subservice name in the initial message as well
as in subsequent daily updates. However, for subscriptions with filters, users will receive all Events in the initial message,
but only specified Events in subsequent daily updates.
CODE EXAMPLE
An example can be found in the B-PIPE SDK for C++, Java and .NET. as follows:
1) SourceRefSubscriptionExample — This example demonstrates how to make a simple Source Reference
subscription for one (or more) list; it sends all of the Messages to the console window.
This C++ code snippet demonstrates how to subscribe for streaming source reference data.
For additional information, refer to the “Reference Services and Schemas Guide.”
Note that it includes a single main field (VWAP) and two override field/value pairings
(VWAP_START_TIME=10:00 and VWAP_END_TIME=16:00).
User can select the single topic overload of the ADD method and pass the entire string formulated above or break down
the string into topic, fields and overrides; user can then use that applicable overload of the ADD method.
The following code sample demonstrates how this can be accomplished. The response will return a Message containing a
selection of VWAP fields.
<C++>
// Assume that session already exists and "//blp/mktvwap" service
// has been opened.
SubscriptionList subscriptions;
subscriptions.add("//blp/mktvwap/ticker/IBM US Equity",
"VWAP",
"VWAP_START_TIME=10:00&VWAP_END_TIME=16:00"
CorrelationId(10));
session.subscribe(subscriptions);
For additional information, refer to the “Reference Services and Schemas Guide.”
The three types of order books: Market-By-Order (MBO), Market-By-Level (MBL) and Market Maker Quote (MMQ). An
exchange that operates an order book may provide only MBL data, only MBO data or both MBO and MBL data. An
exchange that operates a market maker quote book will provide MMQ data. The three order/quote book update methods:
Replace-By-Position (RBP), Add-Mod-Delete (AMD) and Replace-By-Broker (RBB).
For additional information, refer to the “Reference Services and Schemas Guide.”
<C++>
// Assume that the blp/mktbar service has already been opened successfully.
SubscriptionList d_subscriptions = new SubscriptionList;
d_subscriptions.add(
"//blp/mktbar/ticker/VOD LN Equity",
"LAST_PRICE",
"bar_size=5&start_time=13:30&end_time=20:00",
CorrelationId(1));
d_session.subscribe(d_subscriptions);
MarketBarEnd — Occurs when the last market bar has been received (the end_time has been reached). This
Message contains DATE and TIME.
MarketBarIntervalEnd – Sent consistently at the end of each bar interval even if there are no TRADEs for the
security at the moment.
Note that no initial summary is returned for streaming intraday bars. A reference data request or a
subscription is required to get an initial paint. When a market bar subscription is set to return delayed data,
the market bar start Message will not be returned until the delay period has passed.
For additional information, refer to the “Reference Services and Schemas Guide.”
/secids Request for one-time list of instruments that match a given <topic>. It will
always be “Secids List.” See table below for additional information and an
example.
<topic type> /cusip Requests by CUSIP
/sedol Requests by SEDOL
/isin Requests by ISIN
/bsid Requests by Bloomberg Security Identifier
/bsym For requests by Bloomberg Security Symbol
/buid For requests by Bloomberg Unique Identifier
/eid For requests by Entitlement ID
/source For requests by Source syntax
//blp/mktlist/chain/bsym/FTUK/UKX Index;
Index List /bsym /<source>/<identifier> Daily
class=option
* Denotes whether that particular subscription (based on the <topic type> of the subscription string) will refresh and at what periodicity. For Daily
refreshes, this will occur at the start of a new market day.
** The “//blp/mktlist” service currently does not support the “/ticker” topic type.
CODE EXAMPLES
Two separate examples can be found in the B-PIPE SDK for C++, Java and .NET. They are as follows:
MarketListSubscriptionExample
This example demonstrates how to make a simple Market List “chain” subscription for one, or more, securities and
displays all of the Messages to the console window.
MarketListSnapshotExample
This example demonstrates how to make a Market List “secids” one-time request and displays the Message to the
console window.
Now that the user has a better understanding of how a //blp/mktlist subscription or one-time request string is formed, the
time has come to use it in the application. The following sections provide further details about how to subscribe to a chain
of instruments and request a list of members.
For additional information, refer to the “Reference Services and Schemas Guide.”
For additional information, refer to the “Reference Services and Schemas Guide.”
A successful FieldResponse will contain an array of FieldData. The FieldData contains the field’s unique ID and
information about the field. This example shows how to process a single FieldResponse. It is assumed that an Event was
received with either a RESPONSE or PARTIAL_RESPONSE type prior to running this processFieldResponse method:
<C++>
MessageIterator msgIter(event);
while (msgIter.next()) {
Message msg = msgIter.message();
Element fields = msg.getElement("fieldData");
int numElements = fields.numValues();
printHeader();
for (int i=0; i < numElements; i++) {
printField (fields.getValueAsElement(i));
}
std::cout << std::endl;
}
if (event.eventType() == Event::RESPONSE) {
break;
}
break;
}
The above code snippet does not provide the code for either the printField or printHeadermethods. To view these, refer to
the SimpleFieldInfoExample example installed with the C++ API SDK.
<C++>
Service fieldInfoService = session.getService("//blp/apiflds");
Request request = fieldInfoService.createRequest("FieldSearchRequest");
request.append("searchSpec", "last price");
Element exclude = request.getElement("exclude")
Exclude.setElement("fieldType", "Static");
std::cout << "Sending Request: " << request << std::endl;
session.sendRequest(request);
A FieldSearchRequest returns a FieldResponse just as a FieldInfoRequest does.
It is assumed that an Event was received with either a RESPONSE or
PARTIAL_RESPONSE type prior to running this processFieldResponse method:
<C++>
MessageIterator msgIter(event);
while (msgIter.next()) {
Message msg = msgIter.message();
Element fields = msg.getElement("fieldData");
int numElements = fields.numValues();
for (int i=0; i < numElements; i++) {
printField (fields.getValueAsElement(i));
}
std::cout << std::endl;
}
if (event.eventType() == Event::RESPONSE) {
break;
}
The above code snippet does not provide the code for the printFieldmethod. To view this, refer to the
SimpleFieldSearchExample example installed with the C++ API SDK.
5.15. INSTRUMENTS
//blp/instruments: The Instruments service is used to perform three types of operations. The first is a Security Lookup
Request, the second is a Curve Lookup Request and the third is a Government Lookup Request. Instruments from a
common source (e.g., NASDAQ) will share an EID. For example, MSFT UQ Equity and INTC UQ Equity both come from
NASDAQ and have EID 14005 (if requested by someone with Level 1 access).
For additional information, refer to the “Reference Services and Schemas Guide.”
subscriptions.add(page.c_str(),
"15-18", // subscribe to rows 15 to 18
new CorrelationID(topic));
RESPONSE BEHAVIOR
Once a subscription has been created and the subscription status Messages have been processed, two Event types
might be received:
getElement("securityName").setValue("IBM US Equity");
getElement("dataRange").setChoice("historical");
getElement("dataRange").getElement("historical");
historicalEle.getElement("startDate").setValue("20100501");
historicalEle.getElement("endDate").setValue("20100528");
dmiStudyEle.getElement("period").setValue(15);
RESPONSE BEHAVIOR
A successful studyResponse holds information on the requested security. It contains a studyDataTable with one
studyDataRow for each interval returned.
if (security.hasElement("securityError"))
{
printErrorInfo("\tSECURITY FAILED: ", security);
return;
}
Element fields = msg.getElement(STUDY_DATA);
if (numValues > 0)
{
for (int j = 0; j < numValues; ++j)
{
Element field = fields.getValueAsElement(j);
int numElems= field.numElements();
{
Element element = field.getElement(k);
std::cout << "\t" << element.name() + " = "
}
std::cout << std::endl;
}
}
getElement("securityName").setValue("IBM US Equity");
// set to intraday
getElement("dataRange").getElement("intraday");
// set intraday price data
intradayEle.getElement("endDate").setValue("2010-05-27T13:30:00");
getElement("smavgStudyAttributes");
smavgStudyEle.getElement("period").setValue(15); // SMAVG study interval
smavgStudyEle.getElement("priceSourceClose").setValue("close");
RESPONSE BEHAVIOR
A successful studyResponse holds information on the requested security. It contains a studyDataTable with one
studyDataRow for each bar interval returned.
if (security.hasElement("securityError"))
{
printErrorInfo("\tSECURITY FAILED: ", security);
return;
}
Element fields = msg.getElement(STUDY_DATA);
if (numValues > 0)
{
for (int j = 0; j < numValues; ++j)
{
Element field = fields.GetValueAsElement(j);
{
Element element = field.getElement(k);
Std::cout << std::endl;
"priceSourceClose=LAST_PRICE&" \
"priceSourceHigh=HIGH&" \
"priceSourceLow=LOW&" \
"periodicitySelection=DAILY&" \
"period=14"
,new CorrelationID("IBM US Equity_WLPR"));
session.susbcribe (subscriptions);
RESPONSE BEHAVIOR
Once a subscription is established, the stream will supply Messages in SUBSCRIPTION_DATA Events. In addition to the
study field subscribed, users may receive additional study fields, which were not subscribed, in these Messages. These
additional fields are not filtered for the purpose of speed and their inclusion is subject to change at any time.
6. Best Practices
This includes information on how data usage limits work so as developers build apps they can keep this information in
mind to avoid hitting data limits. This section talks about stability, where testing is the key to stable code, as is checking
return values. Following are some recommended best practices to follow when developing Bloomberg API-based
applications:
6.3. EVENTQUEUE
EventQueues can replace the default Session Event queue per Request. The result of a Request can occur in several
Partial Events.
Asynchronous requests can be made blocking a Request after it is made passing an EventQueue, all Events for that
Request will appear on that EventQueue or once the Request is complete.
The function can return the results from parsing all the Events.
An Event is a container for Messages and owns all memory for Messages.
As it can hold many Messages, it can be quite large.
Note: In C++, Messages point inside an Event and the lifespan of a Message must not exceed its Event’s
lifespan.
Element E;
int err=getElement(&E, Name);
if (!err)int valerr=E.getValueAs(&MYVAL);
(Name) obviates the need for a second lookup through a call to the hasElement() method, whose Boolean argument
determines if Null is treated the same way as the field not existing at all.
6.5. MAXEVENTQUEUESIZE
The default for SessionsOptions.maxEventQueueSize is 10,000 and this should always be higher than thenumber of
subscriptions. If more Events exist, they will be dropped. The notification is: SlowConsumer(Hi/Lo)Watermark. Higher
values reduce the chance of clearing the eventQueue and increase potential unmonitored latency and there is a risk of
consuming very high amounts of memory.
6.8. DATETIME
DateTime is basically a struct, and in cases where it is convertible to a native datetime type it is generally better to convert
it to a native type. However, in some cases, it is not convertible, for example, it might only hold a month. Store it in a
standard string format if it does not convert and if it is only displayed and never used for calculations. The format for String
conversion to DateTime is based on field type and must be exact:
6.9. IF CHAINS
It is common in example code to see:
if (msg.hasElement(ELEMENT))
{
myObject.ELEMENT=msg.getAsString(ELEMENT);
}
{
if (e.name() == ELEMENT)
{
myObject.ELEMENT=e.getValueAsString();
}
}
This needs to be a per-case evaluation. Based on the number of fields required vs. the number of fields expected in the
Event,
Where ELEMENT
MessageIterator iter(event);
while(iter.next())
{
Message msg=iter.message();
for (int idx = 0;
idx < msg.asElement().getElement("securityData").numValues();
idx++)
{
if (msg.asElement().getElement("securityData")
.getValueAsElement(idx)
.getElement("fieldData")
.hasElement("ELEMENT"))
{
myObject.ELEMENT=
msg.asElement().getElement("securityData")
.getValueAsElement(idx)
.getElement("fieldData")
.getElementAsString("ELEMENT");
}
if (msg.asElement().getElement("securityData")
.getValueAsElement(idx)
.getElement("fieldData")
.hasElement("ELEMENT2"))
{
myObject.ELEMENT2=
msg.asElement().getElement("securityData")
.getValueAsElement(idx)
.getElement("fieldData")
.getElementAsString("ELEMENT2");
}
…
}
}
C++
// This should be moved up to outer loops as follows:
Element securities; // All Security Data
Element security; // Data for just one Security
Element data; // All field data for that security
Element field; // Data for one field
String Element; // Temp storage for String data
MessageIterator iter(event);
while(iter.next()) {
Message msg=iter.message();
if (msg.GetElement(&securities, SECURITY_DATA) != 0) // non 0
means error
next;
int maxIndex=securities.numValues();
for (int idx = 0; idx < maxIndex; ++idx)
{
security=securities.getValueAsElement(idx);
if (security.GetElement(&data, FIELD_DATA) != 0) // non 0 means
error
next;
if (data.GetElement(&field, ELEMENT)) // Note this is a Name now
if (field.getValueAs(&Element) == 0) // 0 means no error
Object.ELEMENT=Element;
if (data.GetElement(&field, ELEMENT2)) // Note this is a Name now
if (field.getValueAs(&Element) == 0) // 0 means no error
Object.ELEMENT2=Element;
…
}
}
- Where ELEMENT, ELEMENT2
Can be any Bloomberg or Local Schema Field string stored in a Name}
7. Event Handling
Asynchronous and synchronous Event handler code is quite similar. However, there are a few notable differences
between the two:
SYNCHRONOUS
Simpler of the two modes to code.
Blocks until an Event becomes available.
Uses the Session.NextEvent method to obtain the next available Event object.
ASYNCHRONOUS
Recommended mode.
Does not block until an Event becomes available. Instead, the Event handler is triggered by a callback.
Requires that an EventHandler object be supplied when creating a Session.
The Session class also provides ways of handling Events synchronously and asynchronously. The simpler of the two is
synchronous Event handling, which requires calling Session.NextEvent to obtain the next available Event object. This
method will block until an Event becomes available. A synchronous request model is well-suited for single-threaded
customer applications.
The alternative and preferred method to handling data request Events is asynchronously, which is accomplished by
supplying an EventHandler object when creating a Session. In this case, the user-defined processEvent method in the
supplied EventHandler will be called by the Bloomberg API when an Event is available. For instance, the C++ API
signature for processEvent method is:
public void processEvent(Event event, Session session) // No exceptions are thrown
The callbacks to the processEvent method will be executed by a thread owned by the Bloomberg API, thereby making the
customer application multi-threaded; consequently, customer applications must ensure that data structures and code
accessed from both its main thread and from the thread running the EventHandler object are thread-safe.
The mode of a Session is determined when it is constructed and cannot be changed subsequently.
As previously discussed, there are two modes for handling data requests: asynchronously and synchronously. These
choices are mutually exclusive:
If a Session is provided with an EventHandler when it is created (i.e., asynchronous mode), then calling its NextEvent
method (used for synchronous mode) will throw an exception.
If no EventHandler is provided with a Session (i.e., synchronous mode), then the only way to retrieve an Event object
is by calling its NextEvent method.
8. Message Types
Once a “//blp/mktdata” subscription is established, the stream will supply Messages in SUBSCRIPTION_DATA Events.
Each Message will contain a MKTDATA_EVENT_TYPE and MKTDATA_EVENT_SUBTYPE value. For instance, the
initial Message returned, identified with SUMMARY/INITPAINT values, will contain a value for all the fields specified in the
subscription. Subsequent Messages may contain values for some or all of the requested Bloomberg fields. It is possible
for a Message to contain none of the requested Bloomberg fields as the Messages are only filtered based on the fields
they could contain rather than the fields they actually contain—many fields in the streaming events are optional. The
Bloomberg API will ensure that all Messages that contain any of the fields users have explicitly subscribed for are pushed
to their application. Finally, the stream may return additional fields in these Messages that were not included in the
subscription. These additional fields are not filtered for the purpose of speed, and their inclusion is subject to change at
any time.
Here is a list of the common MKTDATA_EVENT_TYPE/MKTDATA_EVENT_SUBTYPE value pairings, along with
descriptions that users may see in the SUBSCRIPTION_DATA Event Messages:
9. Error Codes
9.1. COMMON EXCEL ERROR MESSAGE CODES
#N/A Authorization: Indicates missing authorization while trying to access a service for which not privileged for, if no
user information in request (valid user handle is required in every request/subscribe call) or Platform not enabled in
EMRS for particular user.
#N/A Connection: Connection between the BBCOMM (which handles the actual transfer of data from our database
to the user’s PC) and the RTD (which passes requests from Excel to the BBCOMM) has been severed.
#N/A Published Data: N Succeeded, N Failed: Publish Event succeeded with a count of how many specific fields
succeeded and how many failed. At least one field must have “succeed.”
#N/A Requesting Data...: Displays while waiting for formula result to be returned.
#N/A Field Not Applicable: Field is not applicable for the security. For example, trying to retrieve the yield on a stock
or the dividend per share on a bond.
#N/A Invalid Security: Security is not recognized.
9.2.1. GENERAL
9.2.3. //BLP/APIAUTH
(AUTHORIZATION_STATUS, REQUEST_STATUS, RESPONSE and PARTIAL_RESPONSE Events) [Server API and B-
PIPE]
9.2.5. //BLP/REFDATA
(REQUEST_STATUS, RESPONSE and PARTIAL_RESPONSE Events)
users/applications.
SessionClusterInfo - Delivered when the SDK is connected to a cluster and receives initial cluster configuration
information from the Bloomberg infrastructure. The message includes the name of the cluster and a list of end points
within.
SessionClusterUpdate - This is delivered when the SDK is connected to a cluster and receives updated
configuration information about the cluster from the Bloomberg infrastructure. The message includes the name of the
cluster and lists of end points that have been added/removed.
SERVICE_STATUS
ServiceOpened — Service has been opened successfully.
ServiceOpenedFailure — Service has failed to open.
SUBSCRIPTION_DATA
MarketDataEvents — Message contains market data. A list of possible types of market data (i.e.,
MKTDATA_EVENT_TYPE/MKTDATA_EVENT_SUBTYPE) will be covered later in this course in the section
“Understanding Market Data Event Types and Sub-Types.”
SUBSCRIPTION_STATUS
SubscriptionStarted — Subscription has started.
SubscriptionFailed — Subscription has failed. Reason will be determined by its category and description properties.
For instance, if the field mnemonic in the subscription doesn’t exist, then the category will be BAD_FLD and the
description will be “Unknown Field.”
SubscriptionTerminated — Failed to obtain initial paint or concurrent subscription limit has been reached.
SubscriptionStreamActivated — Delivered when a data set of a subscription has been successfully opened. Data
associated with this data set will start ticking afterwards. The message includes a list of data sets that become
activated and a reason for the activation.
SubscriptionStreamDeactivated — delivered when the SDK loses its connectivity to the end point providing an
active data set. Data associated with this data set will stop ticking afterwards. The message includes a list of data sets
that become deactivated and a reason for the deactivation.
PARTIAL_RESPONSE AND RESPONSE
ReferenceDataResponse — Message either contains data (with no errors or exceptions) or contains one of the
following elements (in which case, more details available from its category, subcategory and Message):
a) responseError — For example, if no field was included in the request. In that case, the category will be
BAD_ARGS and the Message will be “No fields specified.”
b) securityError – For example, if the security in the reference data request is invalid, then the category will be
BAD_SEC, the subcategory will be INVALID_SECURITY and the Message will be “Unknown/Invalid Security” .
c) fieldExceptions – For example, if the field in the reference data request is not found in the API Data Dictionary,
then the category will be BAD_FLD, the subcategory will be INVALID_FIELD and the Message will be “Field not
valid”.
REQUEST_STATUS
RequestFailure — Occurs when the request times out on the Bloomberg backend.
AUTHORIZATION_STATUS
AuthorizationSuccess — User was authorized successfully.
AuthorizationFailure — User was not authorized successfully. Reason determined by looking at the Message’s
category, subcategory and properties.
ResponseError — Cause of this error will be known only after looking at Message’s category, subcategory and
properties.
EntitlementChanged — User has logged off and then back on to the Bloomberg Professional service.
AuthorizationRevoked — Reasons could be that either the user logged in to a Bloomberg Professional service other
than the one on the PC on which he is running his application, or the user is locked out of the Bloomberg Professional
service.
ADMIN
SlowConsumerWarning — Receiving the Message indicates client is slow. NO category/subcategory.
SlowConsumerWarningCleared — Receiving the Message indicates client is no longer slow. NO
category/subcategory.
ReferenceDataResponse (choice) = {
securityData[] = {
securityData = {
security = AAPL US Equity
sequenceNumber = 0
fieldData = {
PX_LAST = 442.66
DS002 = APPLE INC
VWAP_VOLUME = 15428164
}
}
}
}
Because the Element ReferenceDataResponse is an array, it allows each response Event to receive data for several of
the requested securities. The Bloomberg API may return a series of Message objects, each containing a separate
ReferenceDataResponse, within a series of Event objects in response to a request. However, each security requested will
appear in only one array entry in only one Message object.
Each element of the securityData array is a SEQUENCE that is also named securityData. Each securityData SEQUENCE
contains an assortment of data, including values for the fields specified in the request. The reply corresponding to the
improperly named security, “INVALID US Equity,” shows that the number and types of fields in a response can vary
between entries.
ReferenceDataResponse (choice) = {
securityData[] = {
securityData = {
security = INVALID US Equity
securityError = {
source = 100::bbdbs1
code = 15
category = BAD_SEC
message = Unknown/Invalid security [nid:100]
subcategory = INVALID_SECURITY
}
sequenceNumber = 2
fieldData = {
}
}
}
}
This response Message has an Element not previously seen named securityError. This Element provides details
explaining why data could not be provided for this security.
Note that sending one unknown security does not invalidate the entire request.
Just printing the response in the default format is educational, but to perform any real work with the response, the values
must be extracted from the received Message and assigned elsewhere for use. The following Event handler demonstrates
how to navigate the Element structure of the ReferenceDataResponse.
The Element method of Message provides a handle for navigating the contents of the Message objects using Element
methods. If an Element object is an array (e.g., securityDataArray), then the numValues method provides the number of
items in the array.
Note that the Element class also provides a similarly named method, numElements (not used in this
example), which returns the number of Element objects in a SEQUENCE.
<C++>
static void handleResponseEvent(Event event) {
MessageIterator iter = event.messageIterator();
while (iter.next()) {
Message message = iter.message();
API LIBRARIES
The object models of the Java, .NET, and C++ API libraries are identical, while the C interface provides a C-style version
of the object model. The C++ libraries are distributed in 64- and 32-bit versions on all platforms, while the .NET/Java API
libraries are 32-bit only. However, the Java and .NET libraries are fully compatible with 64-bit applications and the same
library version can be used in both 32- and 64-bit applications.
The Perl and Python APIs require the installation of the C++ API SDK. The Windows version of the Perl API is supported
only with ActivePerl 5.0, or greater. The Python API is supported with 32- and 64-bit CPython v2.6 and v2.7.
CODE EXAMPLES
The BLPAPI provides a core set of code examples across multiple languages, products and operating systems. These
include examples that demonstrate simple requests and subscriptions, along with those providing full authentication,
authorization and permissioning, and enhanced error and data handling. Install the entire set of product SDKs for each
language (from the “\examples” folder of each SDK installation) and understand what is distributed with each. The product
will dictate which additional examples are provided and their functionality.
Binary examples for the C++ and Java API SDKs are found in the “\bin” folder of each of their SDK installation folders.
They accept command-line parameters to customize how the application will authenticate (if applicable) and what data will
be requested/subscribed/published.
At this time, the Windows SDKs from WAPI <GO> have the most complete set of examples and example functionality.
FUNCTION REFERENCE HELP
Many of the SDKs include function reference help, which is found in the “\doc” folder. The C++ API help is generated by
doxygen, the .NET API help by Sandcastle and the Java API help by javadoc. This is also hosted online at
http://www.bloomberglabs.com/api/documentation/.
13. Request/Response
The Request/Response paradigm is useful in obtaining a one-time response that does not require updates. With this
paradigm, all data is static as opposed to the real-time/delayed streaming data received when making a subscription-
based request.
A static request is made for the most current security data as well as requests for historical end-of-day and intraday data
through the following steps:
1. Establish a connection calling the Session.start method.
2. Open the “//blp/refdata” service using the Session.openService method.
3. Get the “//blp/refdata” service using the Session.getService method.
4. Create a Request object of a type matching the type of request. The valid request types are defined in the API
schema. For instance, to make a reference data request, create a Request object of type “ReferenceDataRequest”;
historical requests would be of type “HistoricalDataRequest.”
5. Add one or more securities and fields to the Request object, making sure that the fields are valid for that type of
request and also the Request/Response paradigm. For instance, “LAST_PRICE” is a real-time field, so it would not be
used for a reference data request (as indicated on FLDS <GO>). However, all real-time fields do have an equivalent
static field and are, therefore, usually valid for any static request. If unsure of a specific field’s availability for the
particular security(ies), use the “FLDS <GO>” function on the Bloomberg Professional service or the API Field
(“//blp/apiflds”) service, which will be covered later in this module.
6. Set any particular elements applicable to that type of request.
7. Submit the request using the Session.sendRequest method.
8. Handle the data and status responses either synchronously or asynchronously; these are returned as Events.
Determine whether the data request has been completely filled by checking the Event type of that Event object. If a
RESPONSE Event type is received, no more data will be returned for that request. However, if a
PARTIAL_RESPONSE Event type is received, this Event contains only a partial response for the user’s request and
further incoming Events must be read until a RESPONSE Event type is retrieved.
<C++>
std::vector<std::string> d_securities;
std::vector<std::string> d_fields;
d_securities.push_back("IBM US Equity");
d_securities.push_back("GOOG Equity");
d_fields.push_back("PX_LAST");
d_fields.push_back("PX_BID");
………
// Assume that the //blp/refdata service has already been opened
Service refDataService = session.getService("//blp/refdata");
Request request = refDataService.createRequest("HistoricalDataRequest");
for(int i = 0; i < (int)d_securities.size(); i++)
{
request.getElement("securities").appendValue(d_securities[i].c_str());
}
for(int k = 0; k < (int)d_fields.size(); k++)
{
request.getElement("fields").appendValue(d_fields[k].c_str());
}
request.set("periodicitySelection", "MONTHLY");
request.set("startDate", "20120101");
request.set("endDate", "20121231");
std::cout << "Sending Request: " << request << std:: endl;
session.sendRequest(request);
continue;
}
Element securityData = msg.getElement(SECURITY_DATA);
Element securityName = securityData.getElement(SECURITY_NAME);
std::cout << securityName << "\n\n";
In the above while() loop, if there are no exceptions or errors, the ProcessFields function is called. To view the code for
this function, look at the HistoryExample C++ example, which is found in the Server C++ API SDK installation. Currently,
this example is not available in the B-PIPE SDK.
<C++>
Service refDataService = session.getService("//blp/refdata");
Request request = refDataService.createRequest("IntradayBarRequest");
// only one security/eventType per request
request.set("security", “IBM US Equity”);
request.set("eventType",“TRADE”);
request.set("interval", 60);
Datetime startDateTime, endDateTime;
getTradingDateRange(&startDateTime, &endDateTime); // Custom function call
request.set("startDateTime", startDateTime);
request.set("endDateTime", endDateTime);
request.set("gapFillInitialBar", true);
std::cout << "Sending Request: " << request << std::endl;
session.sendRequest(request);
The code snippet above demonstrates an IntradayBarRequest “IBM US Equity” for trade bars with an interval of 60
minutes between the start and end date—time that would be set in the getTradingDateRange function.
TRADE
BID
ASK
BID_BEST
ASK_BEST
BID_YIELD
ASK_YIELD
MID_PRICE
AT_TRADE
BEST_BID
BEST_ASK
SETTLE
<C++>
void processMessage(Message &msg)
{
Element data = msg.getElement("tickData").getElement("tickData");
int numItems = data.numValues();
std::cout << "TIME\t\t\t\tTYPE\tVALUE\t\tSIZE\tCC" << std::endl;
std::cout << "----\t\t\t\t----\t-----\t\t----\t--" << std::endl;
std::string cc;
std::string type;
for (int i = 0; i < numItems; ++i) {
Element item = data.getValueAsElement(i);
Datetime time = item.getElementAsDatetime("time");
std::string timeString = item.getElementAsString("time");
type = item.getElementAsString("type");
double value = item.getElementAsFloat64("value");
int size = item.getElementAsInt32("size");
if (item.hasElement("conditionCodes")) {
cc = item.getElementAsString("conditionCodes");
} else {
cc.clear();
}
std::cout.setf(std::ios::fixed, std::ios::floatfield);
std::cout << timeString << "\t"
<< type << "\t"
<< std::setprecision(3)
<< std::showpoint << value << "\t\t"
<< size << "\t" << std::noshowpoint
<< cc << std::endl;
}
}
The named constants were replaced by their explicit element strings for clarity. However, for best practices, define these
element strings using the Name class as this is more efficient and less prone to errors.
<C++>
void blpapi::Session::sendRequest(const Request& request,
const CorrelationId& correlationId = CorrelationId(),
EventQueue* eventQueue=0,
const char* requestLabel=0,
int requestLabelLen=0)
In the first overload, send the specified Request object; in the second overload; send the specified request using the
specified Identity for authorization.
If the optionally specified CorrelationID is supplied, use it, otherwise create a CorrelationID. The actual
CorrelationID used is returned. If the optionally specified EventQueue is supplied, all Events relating to this request
will arrive on that EventQueue. If the optional requestLabel and requestLabelLen are provided, they define a string
that will be recorded along with any diagnostics for this operation. There must be at least requestLabelLen printable
characters at the location requestLabel.
A successful request will generate zero or more PARTIAL_RESPONSE Messages followed by exactly one RESPONSE
Message. Once the final RESPONSE Message has been received, the CorrelationID associated with this request
may be reused. If the request fails at any stage, a REQUEST_STATUS will be generated after which the
CorrelationID associated with the request may be reused.
Most applications will only use a single Session. However, the Bloomberg API allows the creation of multiple Session
objects. Multiple instances of the Session class do not contend and thus allow for efficient multi-threading.
There is no reason to create additional threads as the Bloomberg API already utilizes multiple threads where deemed
necessary to provide the most efficient handling of connections and data responses.
To implement a worker thread that would perform any processing required once subscription-based tick data has been
received on the Bloomberg API-owned thread, users must ensure that all of the ticks retain their order (i.e., sequence).
However, the option to create a thread model is available and it may be necessary under certain circumstances, for
example, when subscribing to a large volume of active instruments with a lot of processing/analysis performed on those
ticks.
For request/response type data, notice that the Session.sendRequest method accepts an EventQueue. This allows the
user to specify an Event handler for that particular request. This allows the handling of static data requests on a separate
thread, while a subscription-based request is being handled on the supplied Event handler when the Session object was
created.
EventDispatchers allow dispatching Events from multiple threads. If EventDispatcher is not specified, a default one is
created for the Session. EventDispatchers can be shared across Event queues, thus a pool of threads can be created to
dispatch Events from multiple Event queues. To use an EventDispatcher, create an EventDispatcher with the number of
threads needed for dispatching Events and pass to the Session at construction time. The Session will then use this
EventDispatcher for dispatching Events.
session.QueueEvents = True
session.Start
session.OpenService "//blp/refdata"
Set refdataservice = session.GetService("//blp/refdata")
session.SendRequest req
Start Date The start date for the historical request. Element: startDate
Element value (string): yyyymmdd
End Date The end date for the historical request Element: endDate
Element value (string): yyyymmdd
Calendar Codes Returns the data based on the calendar of the Element: calendarCodeOverride
(CDR) specified country, exchange or region from CDR Element value (string): CDR<GO> Calendar
<GO>. It’s arguments are a two-character Type
calendar code null terminated string. This will
cause the data to be aligned according to the
calendar, including calendar holidays. This
applies only to DAILY requests.
Currency (FX) Amends the value from local currency of the Element: currency
security to the desired currency. Element value (string): Currency of the ISO
code. e.g., USD, GBP
16. Troubleshooting
GATHER ALL NECESSARY INFORMATION TO REPLICATE ISSUE
Product (B-PIPE, SAPI, DAPI, COM v3 Data Control, etc.)
BMDS, ASID, SID
Instruments/fields/date-time range affected
Type of affected data request (subscription, reference data request, historical data request, etc.)
Steps to reproduce
USE DEMO TOOL/SAMPLE PROJECT
Replicate the issue by running the Demo Tool or sample project from the SDK package. This can identify issues with the
source code by comparing the results from the Demo Tool and whether the issue is universal or only in the local
environment.
CONNECTIVITY ISSUES
1. Confirm if host and port are correctly specified.
2. Telnet to host and port and look for server response.
3. For DAPI, confirm if bbcomm.exe is running in task manager.
4. If process is running, run demo tool and see if they can connect.
5. Check for firewall blocking.
DATA DISCREPANCY
1. Check user entitlement.
2. Ensure that the pricing source is consistent between Terminal/Excel/API via {ALLQ <GO>}, {FLDS <GO>}, Demo
Tool, etc.
3. Check the source code and make sure that any request parameters that could affect outcome are correctly set up.
Request parameters to check include “adjustmentFollowDPDF,” “adjustmentNormal,”
“adjustmentSplit,”“pricingOption,” etc.
4. Check the source code and make sure that overrides are correctly requested as follows:
Element overrides = request["overrides"];
Element override1 = overrides.AppendElement();
override1.SetElement("fieldId", "BEST_DATA_SOURCE_OVERRIDE");
override1.SetElement("value", "BLI");
5. If the problem is resolved, do a clean install of the Bloomberg Professional service and make sure BBCOMM starts
without having to manually run BBCOMM.
SCENARIO #2: SPECIFY “SHOW QRM EQUIVALENT” IN DESKTOP API IN C#
Excel spreadsheet displays condition codes for {AAPL UW Equity} by specifying: “=BDH(……,”CondCodes=S”,…..”.
Programatically:
set “includeNonPlottableEvents=true” and “includeConditionCodes=”true”:
request.set(“includeNonPlottableEvents”,true)
request.set(“includeConditionCodes”,true)
Refer to Services and Schema Reference Guide for the details of configurable parameters for an Intraday Tick Request.
Note that timestamps are in GMT for API and in local time for Excel (if BDx() formula used).
BLPAPI_LOGLEVEL=DEBUG
BLPAPI_LOGFILE=c:\blpapilog.txt
Java — Add the following parameters when running the Java application:
Dcom.bloomberglp.blpapi.logLevel=FINER
Dcom.bloomberglp.blpapi.logfolder=C:\
C# — Add listeners by using App.config to the project.
Sample App.config file is as follows: