Main Page > Articles > Algorithmic Trading > Core Architecture of a Python Trading Bot

Core Architecture of a Python Trading Bot

From TradingHabits, the trading encyclopedia · 5 min read · February 28, 2026
The Black Book of Day Trading Strategies
Free Book

The Black Book of Day Trading Strategies

1,000 complete strategies · 31 chapters · Full trade plans

Event-Driven vs. Sequential Architecture

The architecture of a trading bot is a important decision that dictates its performance, scalability, and ability to react to market events. The two primary architectural patterns to consider are sequential and event-driven. A sequential architecture executes a predefined series of steps in a loop. For instance, it might fetch data, apply a strategy, execute a trade, and then repeat. This linear approach is simple to implement and debug, making it suitable for straightforward, low-frequency strategies. However, its rigid structure is a significant drawback in the dynamic world of trading. A sequential bot can only process one piece of information at a time and may miss important market movements while occupied with a different part of its loop. This inherent latency makes it ill-suited for strategies that require rapid responses to unpredictable events.

In contrast, an event-driven architecture is designed to react to a stream of incoming events, such as price ticks, order book updates, or news alerts. Each event is a discrete piece of information that is placed onto a queue. The system then processes these events asynchronously, allowing for concurrent handling of multiple data streams and immediate reaction to new information. This model is far more aligned with the nature of financial markets, where opportunities can appear and disappear in milliseconds. The trade-off for this responsiveness is increased complexity. Event-driven systems require careful management of state, concurrency, and the flow of information between components, often necessitating a more sophisticated design involving message queues and dedicated handlers for different event types.

Component Breakdown

A robust event-driven trading bot is typically composed of several key, decoupled components, each with a specific responsibility. This separation of concerns enhances modularity, making the system easier to develop, test, and maintain.

Data Handler

The Data Handler is the bot's connection to the outside world. Its sole purpose is to subscribe to market data feeds from one or more sources and transform the raw data into a standardized format that the rest of the system can understand. This component should be capable of handling various data types, including tick data, bar data (OHLCV), and order book updates. Upon receiving new market data, the Data Handler creates a MarketEvent and places it onto the central event queue.

python
class DataHandler:
    def __init__(self, events):
        self.events = events

    def on_receive(self, data):
        # Convert raw data to a standardized format
        market_event = self._create_market_event(data)
        self.events.put(market_event)

    def _create_market_event(self, data):
        # Logic to create a MarketEvent object
        pass

Strategy

The Strategy component is the core logic of the trading bot. It receives MarketEvents from the event queue and analyzes them to identify trading opportunities. When a potential trade is found, the Strategy component generates a SignalEvent, which contains the symbol, direction (long or short), and any other relevant information. This event is then placed back onto the event queue for the next component to process. A system can run multiple strategy components simultaneously, allowing for diversification across different trading ideas.

python
class Strategy:
    def __init__(self, events):
        self.events = events

    def on_market_event(self, event):
        # Analyze market data and generate signals
        if self._signal_condition_met(event):
            signal_event = self._create_signal_event(event)
            self.events.put(signal_event)

    def _signal_condition_met(self, event):
        # Logic to determine if a trading signal should be generated
        pass

    def _create_signal_event(self, event):
        # Logic to create a SignalEvent object
        pass

Execution Handler

The Execution Handler is responsible for acting on SignalEvents. It receives these events from the queue and translates them into actual orders to be sent to the broker. This component manages the complexities of order submission, including selecting the appropriate order type (market, limit, stop), handling API connections, and confirming that orders have been received by the exchange. Once an order is placed, the Execution Handler creates an OrderEvent and adds it to the event queue.

python
class ExecutionHandler:
    def __init__(self, events, broker_api):
        self.events = events
        self.broker_api = broker_api

    def on_signal_event(self, event):
        # Create and send an order to the broker
        order = self._create_order_from_signal(event)
        self.broker_api.send_order(order)
        order_event = self._create_order_event(order)
        self.events.put(order_event)

    def _create_order_from_signal(self, event):
        # Logic to create an order object for the broker API
        pass

    def _create_order_event(self, order):
        # Logic to create an OrderEvent object
        pass

Portfolio Manager

The Portfolio Manager is the final piece of the puzzle. It listens for FillEvents, which are generated by the Execution Handler when an order is successfully executed. The Portfolio Manager uses this information to update the bot's internal representation of its portfolio, including positions, cash balance, and overall exposure. It is also responsible for risk management, calculating performance metrics, and potentially generating OrderEvents of its own to rebalance the portfolio or exit positions based on risk parameters.

python
class PortfolioManager:
    def __init__(self, events):
        self.events = events
        self.positions = {}
        self.cash = 100000.0

    def on_fill_event(self, event):
        # Update portfolio based on the executed trade
        self._update_positions(event)
        self._update_cash(event)

    def _update_positions(self, event):
        # Logic to update the positions dictionary
        pass

    def _update_cash(self, event):
        # Logic to update the cash balance
        pass

Connecting Components with a Message Queue

The event queue is the backbone of an event-driven trading bot, acting as the central nervous system that connects all the components. A message queue is a software component that allows different parts of a system to communicate asynchronously. Popular choices for implementing a message queue in a Python trading bot include RabbitMQ and ZeroMQ.

RabbitMQ is a robust, feature-rich message broker that implements the Advanced Message Queuing Protocol (AMQP). It provides advanced features like message persistence, delivery acknowledgements, and flexible routing rules. This makes it a good choice for complex systems where reliability and message ordering are important. However, it also introduces an additional dependency and requires a separate server process.

ZeroMQ, on the other hand, is a lightweight, embeddable messaging library. It operates without a central broker, allowing components to communicate directly with each other in various patterns (e.g., publish-subscribe, request-reply). This results in lower latency and a simpler deployment, but it also means that the application is responsible for handling tasks like message routing and persistence. The choice between RabbitMQ and ZeroMQ depends on the specific requirements of the trading bot, with RabbitMQ being favored for its robustness and ZeroMQ for its low latency and simplicity.

By using a message queue to decouple the components, the trading bot becomes highly scalable and resilient. Individual components can be developed, tested, and deployed independently. If one component fails, the others can continue to operate, and the system can be designed to handle such failures gracefully. This modular architecture is the foundation for building a sophisticated and reliable automated trading system.