QuickFix C++: how to continue reading in market data while another function is running?

Viewed 30

Goal:

To continue printing out market data messages coming from a server, whilst another function containing a while loop listens for an input from another non-market data information source. Effectively, the function that listens for market data should always run regardless of what other functions are running.

Details:

The program below successfully sends a market data request message to the server. Market data messages containing trade information such as bids and asks is then continually printed, as required. Another function is then called which listens out for some input from an informational source using a while loop.

The function that detects when there is a new market data message is Application::onMessage(const FIX44::MarketDataSnapshotFullRefresh& mdMessage, const FIX::SessionID& session).

Problem:

When the second function that listens for some input is called, the stream of market data messages printed to the terminal is stopped until an input has been received, so it seems there is some blocking behaviour.

Simplified program:

#include "Application.h"
#include "quickfix/Session.h"

#include <iostream>

static bool listeningToMarketData = false;
static bool requestMadeAlready = false;

// Output when logged on
void Application::onLogon( const FIX::SessionID& sessionID ) {
    std::cout << std::endl << "Logon - " << sessionID << std::endl;
}

// Output when logged out
void Application::onLogout( const FIX::SessionID& sessionID ) {
    std::cout << std::endl << "Logout - " << sessionID << std::endl;
}

// Admin output sending from client
void Application::toAdmin( FIX::Message& message, const FIX::SessionID& sessionID) {

    // Set logon msg Username/Password
    if (FIX::MsgType_Logon == message.getHeader().getField(FIX::FIELD::MsgType))
    {
        message.getHeader().setField(FIX::Username("XXXXX"));
        message.getHeader().setField(FIX::Password("XXXXX"));
    }
}

// Output coming from server
void Application::fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType ) {
    crack( message, sessionID );
    std::cout << std::endl << "INCOMING: " << message << std::endl;
}

// Output sending from this client
void Application::toApp( FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::DoNotSend ) {
    try {
        FIX::PossDupFlag possDupFlag;
        message.getHeader().getField( possDupFlag );
        if ( possDupFlag ) throw FIX::DoNotSend();
    }
    catch ( FIX::FieldNotFound& ) {}

    std::cout << std::endl << "OUTGOING: " << message << std::endl;
}

// Function handling market data
void Application::onMessage(const FIX44::MarketDataSnapshotFullRefresh& mdMessage, const FIX::SessionID& session) {

    static bool isFirstMdMessage = true;
    listeningToMarketData = true;
}

void listenToMarketData() {
        FIX44::MarketDataRequest marketDataRequest(
                              FIX::MDReqID("ABC1"),
                              FIX::SubscriptionRequestType('1'),
                              FIX::MarketDepth(1));

        marketDataRequest.set( FIX::MDUpdateType(0) );
        marketDataRequest.set( FIX::NoMDEntryTypes(2) );
        marketDataRequest.set( FIX::NoRelatedSym(1) );

        FIX44::MarketDataRequest::NoRelatedSym noRelatedSym;
        FIX44::MarketDataRequest::NoMDEntryTypes noMDEntryTypes1;
        FIX44::MarketDataRequest::NoMDEntryTypes noMDEntryTypes2;

        noRelatedSym.set(FIX::SecurityIDSource("8"));
        noRelatedSym.set(FIX::SecurityID("100800"));
        noMDEntryTypes1.set( FIX::MDEntryType('0') ); // Bid
        noMDEntryTypes2.set( FIX::MDEntryType('1') ); // Offer

        marketDataRequest.addGroup( noRelatedSym );
        marketDataRequest.addGroup( noMDEntryTypes1 );
        marketDataRequest.addGroup( noMDEntryTypes2 );

        FIX::Header& mdHeader = marketDataRequest.getHeader();
        mdHeader.setField(FIX::TargetCompID("TARGET"));
        mdHeader.setField(FIX::SenderCompID("SENDER"));

        FIX::Session::sendToTarget(marketDataRequest);
}

void request() {
    requestMadeAlready = true;

    while (true) {
        std::cout << "listening" << std::endl;
        usleep(1000000);
    }
}

// Run the client application
void Application::run() {
    initialiseSystem();
}

// Function initilises market data & web scraper
void Application::initialiseSystem() {

    while (true) {
        try {
            if (!listeningToMarketData) {

                listenToMarketData();
            }

            usleep(5000000);

            if (!requestMadeAlready) {
                request();
            }
        }
        catch ( std::exception & e )
        {
            std::cout << "Message Not Sent: " << e.what() << std::endl;
        }
    }
}

Question:

Q1. How can the program continue to print market data whilst simultaneously allowing another function to listen for some other input?

0 Answers
Related