Mastering a Multi-Threaded Stock Trading System in C++: A Comprehensive Guide

HaykuhiMkrtchyan
11 min readOct 12, 2023

--

In today’s fast-paced financial markets, stock trading systems play a crucial role in facilitating transactions and ensuring the efficient exchange of securities. Building a robust and efficient stock trading system is no small feat, and it requires a comprehensive understanding of object-oriented design, multithreading, and the effective use of C++ and the Standard Template Library (STL).

In this article, we present an all-encompassing guide to crafting a multi-threaded stock trading system in C++. We’ll guide you through the fundamental components and principles essential for developing such a system. It’s important to note that this article provides a high-level overview, and real-world systems will invariably entail greater intricacies and considerations.

What is a Stock Trading System?

A trading system is a software application designed for the purpose of facilitating the buying and selling of financial instruments, including stocks, indices, futures, bonds, currencies, commodities, and derivatives. It serves as a digital platform that enables users to place orders through financial intermediaries like brokerages, dealers, market makers, or stock exchanges via the internet.

Modern online brokerage firms often provide dedicated mobile trading apps that are compatible with both iOS and Android devices. These trading apps empower users to execute financial transactions swiftly and efficiently with a simple tap on their mobile screens. However, the process of selecting the right trading application to match individual needs typically requires careful evaluation and analysis.

Key Features of the Stock Trading System

Let’s explore how this open-source project can elevate your stock trading experience to new heights.

User-Centric Design

In today’s tech-savvy world, an intuitive and user-friendly interface is paramount. The Stock Trading System is engineered with the user in mind, offering an easily navigable platform that puts the power of stock management at your fingertips. Whether you’re a seasoned trader or just beginning your investment journey, the user-centric design ensures that you can quickly access the tools you need. Say goodbye to the hassle of complex interfaces, and hello to a seamless stock trading experience.

Interface displayed to the Client

◭ Real-time Stock Market Data

In stock trading, timely information can mean the difference between seizing an opportunity and missing out. The Stock Trading System keeps you informed with real-time stock market data, offering live stock prices and trading volumes. With this level of real-time insight, you’re always ready to make informed decisions.

Stock information is kept on file available to all Traders

◭ Order Flexibility

The Stock Trading System understands that every trader has a unique investment strategy. That’s why it offers a variety of order types to cater to your specific needs. Whether you prefer market orders for quick execution or limit orders for precise control, the platform empowers you to execute trades with ease. This flexibility means you can tailor your buying and selling decisions to match your investment strategy, all from one convenient platform.

The Trader has the possibility to create 2 types of Orders:

➣ Market Order is a type of financial order used in trading, primarily in stock and securities markets. It is a straightforward order that instructs to trading platform to buy or sell a security immediately at the best available market price. Market orders are executed as soon as possible, without specifying a specific price.

  1. Speed of Execution: Market orders are executed quickly because they prioritize immediate execution at the prevailing market price.
  2. No Price Guarantee: Since market orders don’t specify a price, the execution price may vary slightly from the last traded price. Traders receive the best available price at the time of execution, which can be advantageous when the market is highly liquid.
  3. Certainty of Execution: Market orders are almost always filled because they prioritize execution over price. However, in very volatile markets or for thinly traded securities, the execution price may deviate significantly from the expected market price.
  4. Minimal Control: Traders using market orders have little control over the execution price, making them suitable for investors who prioritize speed and certainty over price.

➣ Limit Order is a type of financial order used in trading, primarily in stock and securities markets. Unlike a market order, which executes at the current market price, a limit order specifies a particular price at which the trader is willing to buy or sell a security. The order is executed only if the market reaches or exceeds the specified limit price.

  1. Price Specification: A limit order allows traders to set a specific price (the limit price) at which they want to buy or sell a stock. The order will not be executed until the market price reaches or surpasses this specified price.
  2. Price Control: Traders using limit orders have greater control over the execution price. They can set their desired price and wait for the market to reach that price level.
  3. No Guaranteed Execution: While limit orders provide price control, they do not guarantee execution. If the market does not reach the specified price, the order may remain unexecuted.

The trader has the opportunity to perform 2 types of actions։

In the Stock Trading System clients have the capability to execute two fundamental types of actions: ‘Buy’ and ‘Sell.’ These two actions are at the core of trading activities and represent the decisions made by investors, traders, and financial institutions.

➣ Buy Orders: The ‘Buy’ order functionality allows Clients to acquire shares of Stocks. It enables them to add to their investment portfolio by purchasing specific assets. Clients who place ‘Buy’ orders are expressing their intention to invest money in the Stock Market, acquiring ownership of stocks for various investment objectives. When creating an Order, the Client must enter a positive number in the “Count of Stocks” field in order to buy the Stocks.

➣ Sell Orders: On the flip side, the ‘Sell’ order functionality permits clients to sell their existing holdings of securities. It allows them to divest their investments, potentially realizing gains or making strategic adjustments to their portfolios. When creating an Order, the Client must enter a negative number in the “Count of Stocks” field in order to sell the Stocks.

◭ Data Analysis and Visualization

Investing wisely requires more than just data; it requires understanding and insight. The Stock Trading System provides comprehensive data analysis tools and visualizations to help you make data-driven investment decisions. With powerful data analysis at your disposal, you’re equipped to make informed choices that align with your financial goals.

◭ Open Source

What truly sets the Stock Trading System apart is its open-source nature. This means the platform is continually evolving and open to contributions from the community. Whether you’re a developer looking to enhance the system or a trader with specific needs, this open-source project ensures that the platform can adapt and grow to meet the demands of its users. It’s not just a trading platform; it’s a collaborative effort to create the best possible trading experience.

Core Technologies Employed

C++ programming language

The foundation of the Stock Trading System is C++, a powerful and versatile programming language known for its efficiency and performance. C++ enables low-level memory management and is well-suited for real-time applications like stock trading.

◭ STL (Standard Template Library)

The Standard Template Library is a collection of template classes and functions that provide general-purpose classes with function templates to solve various problems in C++. It is utilized for data structures and algorithms, stream handling, and other essential functionalities.

The OrderBook class is undeniably one of the most vital components in our project. It plays a central role in the system, as it serves as the repository where we meticulously store and manage all the critical information necessary for the seamless operation of our trading platform. This information includes data about stocks, traders, and orders.

Here we have used std::unordered_map to manage Stocks, Traders, and Orders. This choice of data structure is a powerful and efficient one, and here’s why it’s a good choice:

  1. Fast Access and Retrieval: std::unordered_map provides fast access to elements based on their keys. In the context of the OrderBook, this means you can quickly retrieve information about Stocks, Traders, and Orders by their respective identifiers.
  2. Constant-Time Lookup: The key feature of std::unordered_map is constant-time complexity for searching, insertion, and deletion operations, assuming a well-distributed hash function. This ensures efficient performance even as the number of elements grows.
  3. Customized Key-Value Pairs: Each std::unordered_map can store custom key-value pairs, making it an ideal choice for associating unique identifiers (like stock or trader IDs) with their corresponding data (e.g., Stock objects, Trader objects, or Order lists).
class OrderBook {
public:
OrderBook();
~OrderBook();

public:
void addOrder(ArchivedOrder*);
void addStock(Stock*);
void removeOrder(ArchivedOrder*);
Stock* getStock(int) const;
Trader* getTrader(int) const;

private:
std::unordered_map<int, Stock*> stocks;
std::unordered_map<int, Trader*> traders;
std::unordered_map<int, std::vector<ArchivedOrder*>> orders;
mutable std::mutex mtx;
};

The Trader class is a pivotal element of our project, and its design plays a crucial role in the efficiency and organization of our trading platform. One of the standout features of the Trader class is the utilization of std::vector data structures to manage and store information about Stocks and Orders. This choice of data structure is not arbitrary; it’s a deliberate and powerful selection that offers several advantages.

  1. Dynamic and Flexible: std::vector is a dynamic array that can grow or shrink in size as needed. This adaptability is essential in a trading system where traders may have varying numbers of Stocks and Orders. It ensures that the Trader class can efficiently manage changing amounts of data without a fixed or predefined limit.
  2. Constant-Time Random Access: std::vector provides constant-time random access to elements. This means that Traders can quickly access and retrieve specific Stocks or Orders from their collections, making operations such as finding, modifying, or iterating through the data highly efficient.
  3. Standard C++ Container: std::vector is a widely used and standard container in C++. It offers robust memory management and iterators, making it a dependable choice for maintaining collections of objects.
class Trader {
public:
Trader(int id, double balance) : id(id), balance(balance) {}
virtual ~Trader() = default;

public:
int getID() const;
char getType() const;
double getBalance() const;
const std::vector<Stock*>& getStocks() const;
const std::vector<Order*>& getOrders() const;
void setId(int);
void setType(char);
void setBalance(double);
void addOrder(Order*);
void addStock(Stock*);
Stock* findStock(int) const;
virtual std::string createOrder(Stock*) = 0;

private:
int id;
double balance;
char type;
std::vector<Stock*> stocks;
std::vector<Order*> orders;
};

The use of the std::remove_if algorithm in the removeOrder() function in OrderBook class is a powerful and efficient choice for removing a specific element from a container. It’s part of the C++ Standard Library’s <algorithm> header. Here’s why it’s a good choice and a little about it:

  1. Efficiency: std::remove_if leverages an efficient in-place element rearrangement algorithm. It doesn’t physically remove elements from the container but rather moves elements that do not match the specified condition to the end of the container. This rearrangement is done in linear time, which is generally faster than iterating through the container to manually remove elements.
  2. Maintains Container Integrity: The std::remove_if algorithm ensures that the container remains contiguous and that iterators remain valid. This means it's safe to continue using the modified container and any iterators you had before the removal.
  3. Customizable Condition: std::remove_if allows you to specify a custom condition for removal using a predicate function. In our function, we're removing Orders based on whether they are equal to the Order passed as an argument. This allows for flexibility and fine-grained control over what gets removed.
void OrderBook::removeOrder(ArchivedOrder* order) {
int stockID = order->getStockID();
auto it = orders.find(stockID);
if (it != orders.end()) {
std::vector<ArchivedOrder*>& stockOrders = it->second;
stockOrders.erase(std::remove_if(stockOrders.begin(), stockOrders.end(),
[order](ArchivedOrder* ord) { return ord == order; }), stockOrders.end());
delete order;
if (stockOrders.empty()) {
orders.erase(it);
}
}
}

◭ Multithreading

The Stock Trading System employs multithreading to handle concurrent trading activities efficiently. Multithreading technology is crucial for ensuring the system can process multiple orders and updates in real-time.

◭ Design Patterns

Several design patterns have been implemented in the system to enhance its modularity, extensibility, and maintainability. The following design patterns are integral to the system:

Factory Method Pattern: This pattern is used to create different types of orders (Market Order, Limit Order) in a flexible and extensible manner, abstracting the order creation process.

The provided class diagram illustrates the structure and relationships of the main Factory Design Pattern classes in a trading system, where the trader is a factory in the context of creating an order. And of course, there is a suitable factory for each type of order. In addition to being stored in the Trader’s Orders list, the Orders must also be sent to the Server, who must also store them. After that, our complete Order object, which is created in the createOrder() function and is stored in the Trader’s Orders list, serialized to a String and sent to the Server. Here, for each type of Օrder, a specific serialization algorithm works, thanks to which the data is securely changed and sent to the server. By employing the Factory Method Pattern, the system can easily accommodate new order types in the future, making it highly extensible.

➣ Strategy Pattern: The Strategy Pattern is used to implement different order generation algorithms for each type of order(Market Order, Limit Order).

void Client::clientCreateOrder() {
int stockID = 0;
std::cout << "Enter Stock ID: ";
std::cin >> stockID;
Stock stock;
stock.loadStockFromID(stockID);
std::string message = trader->createOrder(&stock);
sendMessage(message);
}

When the Trader becomes a Client after entering the program, he chooses what activity he will carry out. When Client wants to create an order, he chooses the ID of the desired stock. After that, an Order is created automatically. Since there are two types of Order, a clear algorithm is defined for the creation of each, which is selected by Strategy Pattern Logic depending on the type of Trader. This solution made it possible to get a flexible software system with a simple interface.

Optimizing Data Management for Enhanced Trading System Performance

In our strategic roadmap for enhancing the functionality of our trading system, we have outlined a comprehensive plan that includes the storage of Trader data in separate files. This forward-thinking approach has several distinct advantages, reinforcing the robustness and scalability of our platform.

◭ Saving Traders

The prospect of preserving Trader information in dedicated files is a forward-looking initiative that promises significant benefits. It allows us to maintain an exhaustive historical record of Traders and their trading activities. By saving trader data in separate files, we’re not just recording transactions; we’re archiving a rich tapestry of financial history. This serves as a valuable resource for analyzing trading trends, evaluating performance, and nurturing long-term relationships with our trading community. It aligns perfectly with our commitment to transparency, trust, and accountability.

◭ Switch Traders Type

As part of our ongoing commitment to empowering Traders, we are actively developing a feature that will allow traders to switch between different Trader types, such as transitioning from a Market Trader to a Limit Trader, or vice versa. This innovative capability reflects our dedication to providing traders with the flexibility to adapt their trading strategies to evolving market conditions and personal preferences.

Summary

The Stock Trading System is designed to put the power of stock market investment into your hands. Whether you’re looking to manage your personal portfolio, explore investment opportunities, or engage with a thriving community of investors, this platform provides the tools and resources you need to succeed in the world of stock trading. Get started today and take control of your financial future.

--

--