Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bloomberg Equity Option Chain through API

Tags:

c++

bloomberg

I am currently working on a project that should help me create an implied volatility surface for a given stock. For this purpose, I am writing a script that will download all the available options for this specific stock - from what I've gathered, this is possible by sending a request through the Bloomberg API using bulks fields/overrides. Here is my current code:

d_host = "localhost";
d_port = 8194;
SessionOptions sessionOptions;
sessionOptions.setServerHost(d_host.c_str());
sessionOptions.setServerPort(d_port);
Session session(sessionOptions);
Service refDataService = session.getService("//blp/refdata");
Request request = refDataService.createRequest("ReferenceDataRequest");

request.append("securities", "MSFT US EQUITY");
request.append("fields", "CHAIN_TICKERS");

// add overrides
Element overrides = request.getElement("overrides");
Element override1 = overrides.appendElement();
override1.setElement("fieldId", "CHAIN_PUT_CALL_TYPE_OVRD");
override1.setElement("value", "C");

Element override2 = overrides.appendElement();
override2.setElement("fieldId", "CHAIN_POINTS_OVRD");
override2.setElement("value", 100);

Element override3 = overrides.appendElement();
override3.setElement("fieldId", "CHAIN_EXP_DT_OVRD");
override3.setElement("value", "20250203");

std::cout << "Sending Request: " << request << std::endl;
CorrelationId cid(this);
session.sendRequest(request, cid);

(followed by event handling)

Now I have several issues/questions:

  1. The code compiles without problems, but when running it on the Bloomberg terminal,the following error is printed: bloomberg error How would I go about fixing this problem? I assume I made a mistake somewhere in the override fields..

  2. How would I need to adjust my code to download all options available given a specific maturity, i.e. I want to get a list of all the options until today + 15 years.

  3. How would I then download the implied volatility for each option? Would I need to store the tickers in an array and then send a request for the field "IVOL_MID" for each option or is there some kind of way to obtain all the volatilities at once?

Edit: Here is the code of my event handler, since that seems to be the problem.

    session.sendRequest(request, cid);

    while (true)
    {
        Event event = session.nextEvent();
        MessageIterator msgIter(event);
        while (msgIter.next()) {
            Message msg = msgIter.message();
            if (msg.correlationId() == cid) {
                processMessage(msg);
            }
        }
        if (event.eventType() == Event::RESPONSE) {
            break;
        }
    }




 void processMessage(Message &msg)
{
    Element securityDataArray = msg.getElement(SECURITY_DATA);
    int numSecurities = securityDataArray.numValues();
    for (int i = 0; i < numSecurities; ++i) {
        Element securityData = securityDataArray.getValueAsElement(i);
        std::cout << securityData.getElementAsString(SECURITY)
            << std::endl;
        const Element fieldData = securityData.getElement(FIELD_DATA);
        for (size_t j = 0; j < fieldData.numElements(); ++j) {
            Element field = fieldData.getElement(j);
            if (!field.isValid()) {
                std::cout << field.name() << " is NULL." << std::endl;
            }
            else {
                std::cout << field.name() << " = "
                    << field.getValueAsString() << std::endl;
            }
        }

        Element fieldExceptionArray =
            securityData.getElement(FIELD_EXCEPTIONS);
        for (size_t k = 0; k < fieldExceptionArray.numValues(); ++k) {
            Element fieldException =
                fieldExceptionArray.getValueAsElement(k);
            std::cout <<
                fieldException.getElement(ERROR_INFO).getElementAsString(
                "category")
                << ": " << fieldException.getElementAsString(FIELD_ID);
        }
        std::cout << std::endl;
    }
like image 491
Olorun Avatar asked Feb 04 '15 04:02

Olorun


People also ask

What is Blpapi?

BLPAPI is the programming interface for Bloomberg's Desktop and Server API products as well as for Managed B-Pipe and Platform (http://open.bloomberg.com). Built on a flexible service-oriented architecture, BLPAPI supports both request/ response and publish/subscribe paradigms.


2 Answers

The problem is in the event handling code that you are not showing. You are probably parsing it incorrectly.

Running your query I get the following result:

MSFT US 01/20/17 C23
MSFT US 01/20/17 C25
MSFT US 01/20/17 C30
MSFT US 01/20/17 C33
MSFT US 01/20/17 C35
MSFT US 01/20/17 C38
MSFT US 01/20/17 C40
MSFT US 01/20/17 C43
MSFT US 01/20/17 C45
MSFT US 01/20/17 C47
MSFT US 01/20/17 C50
MSFT US 01/20/17 C52.5
MSFT US 01/20/17 C55
MSFT US 01/20/17 C57.5
MSFT US 01/20/17 C60
MSFT US 01/20/17 C65
MSFT US 01/20/17 C70

Note: I'm using the Java API but it is essentially the same.


UPDATE:

your code does not parse the field data array element properly: the returned data contains an array of sequences so you need to parse it in two steps. Instead of field.getValueAsString(), you should have a code that looks like this (it's in Java and not tested):

//...
for (int i = 0; i < field.numValues(); i++) {
  Element sequence = field.getValueAsElement(i);
  ElementIterator it = sequence.elementIterator();
  while (it.hasNext()) {
    Element e = it.next();
    System.out.println(e.getValueAsString());
  }

If that does not work I suggest you debug your code step by step and inspect the type of data you receive and handle it accordingly.

For more details you should read the Developer's guide, in particular A.2.3.

like image 184
assylias Avatar answered Oct 12 '22 10:10

assylias


As seen in the other answer, the problem lies in the event handling so I've rewritten that part using some examples from the Bloomberg API emulator.

session.sendRequest(request, cid);
bool continueToLoop = true;
while (continueToLoop)
{
    Event evt = session.nextEvent();
    switch (evt.eventType())
    {
        case Event::RESPONSE:
            continueToLoop = false; //fall through
        case Event::PARTIAL_RESPONSE:
            ProcessReferenceDataEvent(evt);
        break;
     }
}

void ProcessReferenceDataEvent(Event evt)
{
    const string level1 = "";
    const string level2 = "\t";
    const string level3 = "\t\t";
    const string level4 = "\t\t\t";

    std::cout << endl << endl;
    std::cout << level1 << "EventType = " << evt.eventType();

    MessageIterator iter(evt);
    while (iter.next())
    {
        Message msg = iter.message();

        std::cout << endl << endl;
        std::cout << level1 << "correlationID = " << msg.correlationId().asInteger() << endl;
        std::cout << level1 << "messageType = " << msg.messageType().string() << endl;
        std::cout << endl << endl;
        Element SecurityDataArray = msg.getElement(SECURITY_DATA);
        int numSecurities = SecurityDataArray.numValues();
        for (int valueIndex = 0; valueIndex < numSecurities; valueIndex++)
        {
            Element SecurityData = SecurityDataArray.getValueAsElement(valueIndex);

            string Security = SecurityData.getElementAsString(SECURITY);
            std::cout << level2 << Security << endl;

            bool hasFieldErrors = SecurityData.hasElement("fieldExceptions", true);
            if (hasFieldErrors)
            {
                Element FieldErrors = SecurityData.getElement(FIELD_EXCEPTIONS);
                for (size_t errorIndex = 0; errorIndex < FieldErrors.numValues(); errorIndex++)
                {
                    Element fieldError = FieldErrors.getValueAsElement(errorIndex);
                    string fieldId = fieldError.getElementAsString(FIELD_ID);

                    Element errorInfo = fieldError.getElement(ERROR_INFO);
                    string source = errorInfo.getElementAsString("source");
                    int code = errorInfo.getElementAsInt32("code");
                    string category = errorInfo.getElementAsString("category");
                    string strMessage = errorInfo.getElementAsString("message");
                    string subCategory = errorInfo.getElementAsString("subcategory");

                    cerr << level3 << "field error:" << endl;
                    cerr << level4 << "fieldId = " << fieldId << endl;
                    cerr << level4 << "source = " << source << endl;
                    cerr << level4 << "code = " << code << endl;
                    cerr << level4 << "category = " << category << endl;
                    cerr << level4 << "errorMessage = " << strMessage << endl;
                    cerr << level4 << "subCategory = " << subCategory << endl;
                }
            }

            bool isSecurityError = SecurityData.hasElement("securityError", true);
            if (isSecurityError)
            {
                Element secError = SecurityData.getElement("securityError");
                string source = secError.getElementAsString("source");
                int code = secError.getElementAsInt32("code");
                string category = secError.getElementAsString("category");
                string errorMessage = secError.getElementAsString("message");
                string subCategory = secError.getElementAsString("subcategory");

                cerr << level3 << "security error:" << endl;
                cerr << level4 << "source = " << source << endl;
                cerr << level4 << "code = " << code << endl;
                cerr << level4 << "category = " << category << endl;
                cerr << level4 << "errorMessage = " << errorMessage << endl;
                cerr << level4 << "subCategory = " << subCategory << endl;
            }
            else
            {
                Element FieldData = SecurityData.getElement(FIELD_DATA);


                double pxLast = FieldData.getElementAsFloat64("PX_LAST");
                double bid = FieldData.getElementAsFloat64("BID");
                double ask = FieldData.getElementAsFloat64("ASK");
                string ticker = FieldData.getElementAsString("TICKER");

                std::cout << level3 << "fields: " << endl;
                std::cout << level4 << "PX_LAST = " << pxLast << endl;
                std::cout << level4 << "BID = " << bid << endl;
                std::cout << level4 << "ASK = " << ask << endl;
                std::cout << level4 << "TICKER = " << ticker << endl;

                bool excludeNullElements = true;
                if (FieldData.hasElement("CHAIN_TICKERS", excludeNullElements))
                {
                    Element chainTickers = FieldData.getElement("CHAIN_TICKERS");
                    for (size_t chainTickerValueIndex = 0; chainTickerValueIndex < chainTickers.numValues(); chainTickerValueIndex++)
                    {
                        Element chainTicker = chainTickers.getValueAsElement(chainTickerValueIndex);
                        string strChainTicker = chainTicker.getElementAsString("Ticker");

                        std::cout << level4 << "CHAIN_TICKER = " << strChainTicker << endl;
                    }
                }
                else
                {
                    std::cout << level4 << "NO CHAIN_TICKER information" << endl;
                }
            }
        }
    }
}

Regarding the second question, the Bloomberg support staff recommended me to just pick an arbitarily high number so that all options would be downloaded, i.e.

override2.setElement("fieldId", "CHAIN_POINTS_OVRD");
override2.setElement("value", 50000);

For the third question, it is possible to download the chain tickers for all maturities by setting the "CHAIN_EXP_DT_OVRD" override to 'ALL' (this part is currently untested):

    Element override3 = overrides.appendElement();
    override3.setElement("fieldId", "CHAIN_EXP_DT_OVRD");
    override3.setElement("value", 'ALL');
like image 23
Olorun Avatar answered Oct 12 '22 11:10

Olorun