Koding Books

Professional, free coding tutorials

Building High-Performance Market Data Processors in C++

Market data processors collect and process market data in real-time. They are used by various financial institutions, including exchanges, brokers, and hedge funds, to make trading decisions and manage risk.

C++ is a popular programming language for developing market data processors because it is efficient and allows direct control over hardware. It is also a popular language for developing trading algorithms because it is expressive and versatile.

Key Considerations

  • Performance: Market data processors need to be able to process large volumes of data in real-time. C++ is a good choice because it is efficient and allows for direct control over hardware.
  • Scalability: Market data processors need to scale to handle increasing volumes of data and traffic. C++ is a good choice because it is scalable and can be used to develop high-performance distributed systems.
  • Reliability: Market data processors must be reliable and able to handle errors and unexpected events. C++ is a good choice for this because it is a robust language with features such as exception handling and memory management.

C++ implementation

#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <map>
#include <vector>

using namespace std;

// An enum to represent the different types of market data updates
enum class MarketDataUpdateType {
  TRADE,
  ORDER,
  QUOTE
};

// A struct to represent a market data update
struct MarketDataUpdate {
  MarketDataUpdateType type;
  string symbol;
  double price;
  size_t quantity;
  string exchange;
  string feed;
};

// A queue to store market data updates
queue<MarketDataUpdate> marketDataQueue;

// A mutex to protect the queue
mutex marketDataQueueMutex;

// A map to store market data aggregates
map<string, MarketDataUpdate> marketDataAggregates;

// A vector to store real-time alerts
vector<MarketDataUpdate> realTimeAlerts;

// A function to process market data updates
void processMarketDataUpdate(MarketDataUpdate update) {
  // Update the market data aggregates
  marketDataAggregates[update.symbol] = update;

  // Generate real-time alerts
  if (update.type == MarketDataUpdateType::TRADE && update.exchange == "NYSE" && update.price > 100.00) {
    realTimeAlerts.push_back(update);
  }
}

// A thread function to process market data updates
void marketDataProcessor() {
  while (true) {
    // Get the next market data update from the queue
    MarketDataUpdate update;
    {
      lock_guard<mutex> lock(marketDataQueueMutex);
      if (marketDataQueue.empty()) {
        continue;
      }
      update = marketDataQueue.front();
      marketDataQueue.pop();
    }

    // Process the market data update
    processMarketDataUpdate(update);
  }
}

// A function to filter market data updates
bool filterMarketDataUpdate(MarketDataUpdate update) {
  return update.type == MarketDataUpdateType::TRADE && update.exchange == "NYSE";
}

// A function to aggregate market data updates
MarketDataUpdate aggregateMarketDataUpdates(MarketDataUpdate update1, MarketDataUpdate update2) {
  MarketDataUpdate aggregateUpdate;
  aggregateUpdate.type = MarketDataUpdateType::TRADE;
  aggregateUpdate.symbol = update1.symbol;
  aggregateUpdate.exchange = update1.exchange;
  aggregateUpdate.feed = update1.feed;
  aggregateUpdate.price = (update1.price + update2.price) / 2.0;
  aggregateUpdate.quantity = update1.quantity + update2.quantity;
  return aggregateUpdate;
}

// A function to send a real-time alert
void sendRealTimeAlert(MarketDataUpdate alert) {
  cout << "Real-time alert: " << alert.symbol << " at price " << alert.price << " on exchange " << alert.exchange << endl;
}

int main() {
  // Start a thread to process market data updates
  thread marketDataProcessorThread(marketDataProcessor);

  // Add some market data updates to the queue
  marketDataQueueMutex.lock();
  marketDataQueue.push({ MarketDataUpdateType::TRADE, "AAPL", 100.00, 100, "NYSE", "Bloomberg" });
  marketDataQueue.push({ MarketDataUpdateType::TRADE, "GOOG", 120.00, 200, "NASDAQ", "Refinitiv" });
  marketDataQueueMutex.unlock();

  // Filter and aggregate the market data updates
  vector<MarketDataUpdate> filteredUpdates;
  for (MarketDataUpdate update : marketDataQueue) {
    if (filterMarketDataUpdate(update)) {
      filteredUpdates.push_back(update);
    }
  }
  vector<MarketDataUpdate> aggregatedUpdates;
  for (int i = 0; i < filteredUpdates.size() - 1; i += 2) {
    aggregatedUpdates.push_back(aggregateMarketDataUpdates(filteredUpdates[i], filteredUpdates[i + 1]));
  }

  // Send real-time alerts
  for (MarketDataUpdate alert : aggregatedUpdates) {
    sendRealTimeAlert

To execute the above code, you can compile it using a C++ compiler such as g++ or Clang++. Once the code is compiled, you can run it using the generated executable file.

Here are the steps to compile and run the code on Linux or macOS:

  1. Compile the code using the following command:
g++ market_data_processor.cpp -o market_data_processor

This will generate an executable file called market_data_processor.

  1. Run the executable file using the following command:
./market_data_processor

This will start the market data processor.

  1. You can use the queue to send market data updates to the processor. To add an update to the queue, use the following code:

MarketDataUpdate update;
update.type = MarketDataUpdateType::TRADE;
update.symbol = "AAPL";
update.price = 100.00;
update.quantity = 100;

marketDataQueueMutex.lock();
marketDataQueue.push(update);
marketDataQueueMutex.unlock();

  1. The market data processor will process the updates in the marketDataQueue queue. To filter and aggregate the updates, you can use the filterMarketDataUpdate() and aggregateMarketDataUpdates() functions.
  2. To receive real-time alerts, you can subscribe to the realTimeAlerts vector. You will be notified when a new alert is added to the vector.

Here is an example of how to subscribe to real-time alerts:

vector<MarketDataUpdate> realTimeAlerts;

while (true) {
  if (realTimeAlerts.empty()) {
    continue;
  }

  MarketDataUpdate alert = realTimeAlerts.front();
  realTimeAlerts.pop_front();

  // Process the alert
}

Digging into the code

The code above is a simple market data processor in C++. It uses a queue to store market data updates, a mutex to protect the queue, and a map to store market data aggregates. The processor also uses a vector to store real-time alerts.

The processor first gets the next update from the queue to process market data updates. Then, it updates the market data aggregates and generates real-time alerts, if necessary.

To filter and aggregate market data updates, the processor uses the filterMarketDataUpdate() aggregateMarketDataUpdates() functions. The filterMarketDataUpdate() function checks if an update matches the specified criteria. If it does, the update is added to the filteredUpdates vector. Otherwise, the update is discarded.

The aggregateMarketDataUpdates() function combines two market data updates into a single update. The combined update has the following properties:

  • The type is the same as the type of the first update.
  • The symbol is the same as the symbol of the first update.
  • The exchange is the same as the exchange of the first update.
  • The price is the average of the prices of the two updates.
  • The quantity is the sum of the quantities of the two updates.

To receive real-time alerts, the processor subscribes to the realTimeAlerts vector. The processor is notified when a new alert is added to the vector.

The following is a more detailed explanation of the main functions in the code:

  • processMarketDataUpdate(): This function processes a market data update. It updates the market data aggregates and generates real-time alerts if necessary.
  • filterMarketDataUpdate(): This function checks if a market data update matches the specified criteria. If it does, the update is added to the filteredUpdates vector. Otherwise, the update is discarded.
  • aggregateMarketDataUpdates(): This function combines two market data updates into a single update. The combined update has the following properties:
    • The type is the same as the type of the first update.
    • The symbol is the same as the symbol of the first update.
    • The exchange is the same as the exchange of the first update.
    • The price is the average of the prices of the two updates.
    • The quantity is the sum of the quantities of the two updates.
  • sendRealTimeAlert(): This function sends a real-time alert. The alert contains the market data update’s symbol, price, exchange, and feed.

C++ is a powerful language that is well-suited for developing market data processors. It is efficient, allows direct control over hardware, and is expressive and versatile.

Ali Kayani

https://www.linkedin.com/in/ali-kayani-silvercoder007/

Post navigation

Leave a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

Momentum Effect in Commodities Futures

Queues

Digging into General Relativity with C++

Dual Thrust Trading Algorithm