Architecture Overview¶
How FLOX components fit together.
System Layers¶
┌─────────────────────────────────────────────────────────────────┐
│ Your Strategy │
├─────────────────────────────────────────────────────────────────┤
│ EventBus (Disruptor) │ Order Execution │ Risk Management │
├─────────────────────────────────────────────────────────────────┤
│ Connectors │ Order Books │ Symbol Registry │ Replay │
└─────────────────────────────────────────────────────────────────┘
Layer 1: Infrastructure — Connectors, replay, symbol management Layer 2: Core — Event buses, execution, risk Layer 3: Application — Your trading strategies
Data Flow¶
flowchart TD
subgraph External
EX[Exchange API]
end
subgraph Connectors
CONN[IExchangeConnector]
end
subgraph EventBuses[Event Buses - Disruptor Ring Buffers]
TB[TradeBus]
BB[BookUpdateBus]
CB[CandleBus]
end
subgraph Aggregators
CA[CandleAggregator]
end
subgraph Strategies
ST[IStrategy]
end
subgraph Execution
OEB[OrderExecutionBus]
EXE[IOrderExecutor]
RM[IRiskManager]
KS[IKillSwitch]
end
EX --> CONN
CONN --> TB
CONN --> BB
TB --> ST
BB --> ST
TB --> CA
CA --> CB
CB --> ST
ST -->|Order| RM
RM -->|Allowed| KS
KS -->|Not Triggered| EXE
EXE --> OEB
Text representation:
Core Components¶
Engine¶
The Engine class orchestrates the system lifecycle:
class Engine : public ISubsystem
{
public:
Engine(const EngineConfig& config,
std::vector<std::unique_ptr<ISubsystem>> subsystems,
std::vector<std::shared_ptr<IExchangeConnector>> connectors);
void start() override;
void stop() override;
};
- Takes ownership of all subsystems
- Starts subsystems first, then connectors
- Stops connectors first, then subsystems
- No configuration file parsing — you wire components manually
Event Buses¶
All buses use the Disruptor pattern (see The Disruptor Pattern):
| Bus | Event Type | Purpose |
|---|---|---|
TradeBus |
TradeEvent |
Individual trades |
BookUpdateBus |
pool::Handle<BookUpdateEvent> |
Order book snapshots/deltas |
CandleBus |
CandleEvent |
OHLCV candles |
OrderExecutionBus |
OrderEvent |
Order state changes |
Key characteristics: - Lock-free ring buffer - Single producer, multiple consumers - Consumers run in dedicated threads - Backpressure via sequence gating
Connectors¶
IExchangeConnector interface:
class IExchangeConnector
{
public:
virtual ~IExchangeConnector() = default;
virtual void start() = 0;
virtual void stop() = 0;
virtual std::string exchangeId() const = 0;
};
Connectors: - Parse exchange-specific wire protocols - Convert to FLOX event types - Publish to event buses - Run their own network threads
Strategies¶
IStrategy combines ISubsystem + IMarketDataSubscriber:
class IStrategy : public ISubsystem, public IMarketDataSubscriber
{
public:
virtual ~IStrategy() = default;
};
From IMarketDataSubscriber:
- onTrade(const TradeEvent&)
- onBookUpdate(const BookUpdateEvent&)
- onCandle(const CandleEvent&)
From ISubsystem:
- start()
- stop()
Subsystem Interface¶
Everything that participates in engine lifecycle implements:
class ISubsystem
{
public:
virtual ~ISubsystem() = default;
virtual void start() = 0;
virtual void stop() = 0;
};
Subsystems include: - Event buses - Strategies - Aggregators (e.g., CandleAggregator) - Execution trackers - Custom components
Symbol Management¶
Symbols are identified by SymbolId (uint32_t):
SymbolRegistry registry;
registry.registerSymbol("binance", "BTCUSDT"); // Returns SymbolId
auto id = registry.getSymbolId("binance", "BTCUSDT");
Benefits: - Fast comparison (integer vs string) - Compact event structures - Consistent across components
Type System¶
FLOX uses strong types to prevent unit confusion:
| Type | Underlying | Purpose |
|---|---|---|
Price |
Fixed-point | Prices (avoid floating-point) |
Quantity |
Fixed-point | Quantities |
SymbolId |
uint32_t |
Symbol identifier |
OrderId |
uint64_t |
Order identifier |
UnixNanos |
int64_t |
Nanosecond timestamp |
Threading Model¶
┌─────────────────────────────────────────────────────────────┐
│ Main Thread │
│ - Engine lifecycle │
│ - Subsystem start/stop │
└─────────────────────────────────────────────────────────────┘
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Connector │ │ Connector │ │ Connector │
│ Thread(s) │ │ Thread(s) │ │ Thread(s) │
│ - Network I/O │ │ - Network I/O │ │ - Network I/O │
│ - Parsing │ │ - Parsing │ │ - Parsing │
│ - Publishing │ │ - Publishing │ │ - Publishing │
└───────────────┘ └───────────────┘ └───────────────┘
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Bus Consumer │ │ Bus Consumer │ │ Bus Consumer │
│ Thread │ │ Thread │ │ Thread │
│ - Strategy A │ │ - Strategy B │ │ - Aggregator │
└───────────────┘ └───────────────┘ └───────────────┘
- Each connector manages its own threads
- Each bus consumer gets a dedicated thread
- Consumer threads can be pinned to isolated CPU cores
CPU Affinity (Optional)¶
With FLOX_ENABLE_CPU_AFFINITY=ON:
This: - Pins consumer threads to isolated cores - Sets real-time scheduling priority - Enables NUMA-aware core assignment
Next Steps¶
- The Disruptor Pattern — Deep dive into event delivery
- Memory Model — Zero-allocation design
- First Strategy — Write your first strategy