Integration Flow¶
Step-by-step guide to integrating FLOX components into a complete trading system.
Overview¶
flowchart TD
subgraph Setup
A[1. Register Symbols] --> B[2. Create Core Components]
B --> C[3. Create Executors & Connectors]
C --> D[4. Wire Event Delivery]
end
subgraph Runtime
D --> E[5. Launch Components]
E --> F[6. Handle Execution Feedback]
end
subgraph Teardown
F --> G[7. Shutdown]
end
1. Register Symbols¶
Before anything else, define which trading instruments the system will operate on. Each symbol is registered with an internal registry, which assigns a unique identifier and stores metadata.
#include "flox/engine/symbol_registry.h"
SymbolRegistry registry;
// Register symbols with exchange and instrument info
auto btcId = registry.registerSymbol("binance", "BTCUSDT", InstrumentType::PERPETUAL);
auto ethId = registry.registerSymbol("binance", "ETHUSDT", InstrumentType::PERPETUAL);
// Retrieve later by name
auto symbolId = registry.getSymbolId("binance", "BTCUSDT");
Key points:
SymbolIdis a compact integer for fast comparison- Registry maps
(exchange, symbol)pairs toSymbolId - Metadata includes instrument type, tick size, lot size
2. Create Core Components¶
Several core components must be created and wired together:
#include "flox/book/bus/trade_bus.h"
#include "flox/book/bus/book_update_bus.h"
#include "flox/execution/bus/order_execution_bus.h"
#include "flox/execution/order_tracker.h"
// Event buses for market data
auto tradeBus = std::make_unique<TradeBus>();
auto bookBus = std::make_unique<BookUpdateBus>();
// Execution infrastructure
auto execBus = std::make_unique<OrderExecutionBus>();
auto orderTracker = std::make_unique<OrderTracker>();
Component responsibilities:
| Component | Purpose |
|---|---|
SymbolRegistry |
Resolve and map symbols |
OrderTracker |
Monitor orders and maintain state |
TradeBus |
Distribute trade events |
BookUpdateBus |
Distribute order book updates |
OrderExecutionBus |
Distribute execution events |
3. Create Executors and Connectors¶
#include "flox/execution/abstract_executor.h"
#include "flox/connector/abstract_exchange_connector.h"
// Order executor sends orders to exchange
auto executor = std::make_unique<BinanceExecutor>(
transport,
registry,
orderTracker.get()
);
// Connector receives market data
auto connector = std::make_shared<BinanceConnector>(
registry,
*tradeBus,
*bookBus
);
Executor responsibilities:
- Send orders to exchange
- Report order status updates
- Update order tracker
Connector responsibilities:
- Connect to exchange (WebSocket, REST, FIX)
- Parse wire protocol
- Publish events to buses
4. Wire Event Delivery¶
Configure buses to distribute events to subscribers:
#include "flox/strategy/istrategy.h"
// Create strategy
auto strategy = std::make_unique<MyStrategy>(executor.get());
// Subscribe to market data
tradeBus->subscribe(strategy.get());
bookBus->subscribe(strategy.get());
// Subscribe to execution events
execBus->subscribe(strategy.get());
// Add optional subscribers
tradeBus->subscribe(logger.get(), /*optional=*/true);
tradeBus->subscribe(metrics.get(), /*optional=*/true);
Subscriber types:
| Type | Behavior |
|---|---|
| Required | System waits for slow consumers |
| Optional | May miss events if too slow |
Common subscribers:
- Trading strategies
- Data aggregators (bars, VWAP)
- Metric collectors
- Risk modules
- Loggers
5. Launch Components¶
Start components in the correct order:
#include "flox/engine/engine.h"
// Collect all subsystems
std::vector<std::unique_ptr<ISubsystem>> subsystems;
subsystems.push_back(std::move(tradeBus));
subsystems.push_back(std::move(bookBus));
subsystems.push_back(std::move(execBus));
subsystems.push_back(std::move(strategy));
// Collect connectors
std::vector<std::shared_ptr<IExchangeConnector>> connectors;
connectors.push_back(connector);
// Create and start engine
EngineConfig config = loadConfig("config.json");
Engine engine(config, std::move(subsystems), std::move(connectors));
engine.start(); // Blocks until shutdown signal
Startup sequence:
- Event buses start threads
- Connectors establish connections
- Strategies begin processing
- Executors ready to handle orders
6. Handle Execution Feedback¶
When orders are submitted, the system maintains consistency:
// In your executor implementation
void MyExecutor::onOrderFill(const FillMessage& msg) {
// Update tracker
_orderTracker->updateOrder(msg.orderId, OrderStatus::FILLED);
// Emit event
OrderEvent event;
event.order.orderId = msg.orderId;
event.order.status = OrderStatus::FILLED;
event.order.filledQty = msg.quantity;
event.order.avgPrice = msg.price;
_execBus->publish(event);
}
Order lifecycle:
stateDiagram-v2
[*] --> NEW
NEW --> SUBMITTED: send to exchange
SUBMITTED --> ACCEPTED: exchange confirms
SUBMITTED --> REJECTED: validation failed
ACCEPTED --> PARTIALLY_FILLED: partial execution
ACCEPTED --> FILLED: full execution
ACCEPTED --> PENDING_CANCEL: cancel requested
ACCEPTED --> EXPIRED: time-in-force expired
ACCEPTED --> REPLACED: modify accepted
PARTIALLY_FILLED --> PARTIALLY_FILLED: more fills
PARTIALLY_FILLED --> FILLED: complete
PARTIALLY_FILLED --> PENDING_CANCEL: cancel remaining
PENDING_CANCEL --> CANCELED: cancel confirmed
FILLED --> [*]
CANCELED --> [*]
REJECTED --> [*]
EXPIRED --> [*]
Conditional order states (stop-loss, take-profit, trailing stop):
stateDiagram-v2
[*] --> PENDING_TRIGGER: conditional order created
PENDING_TRIGGER --> TRIGGERED: price condition met
PENDING_TRIGGER --> TRAILING_UPDATED: trailing stop adjusted
TRAILING_UPDATED --> PENDING_TRIGGER: continue monitoring
TRIGGERED --> SUBMITTED: becomes regular order
OrderEventStatus values:
| Status | Description |
|---|---|
NEW |
Order created locally |
SUBMITTED |
Sent to exchange |
ACCEPTED |
Exchange acknowledged |
PARTIALLY_FILLED |
Partial execution |
FILLED |
Fully executed |
PENDING_CANCEL |
Cancel request sent |
CANCELED |
Successfully canceled |
EXPIRED |
Time-in-force expired |
REJECTED |
Exchange rejected |
REPLACED |
Order modified (price/qty) |
PENDING_TRIGGER |
Conditional order waiting |
TRIGGERED |
Condition met, converting to market/limit |
TRAILING_UPDATED |
Trailing stop price adjusted |
7. Shutdown Procedure¶
Graceful shutdown ensures no data loss:
// Signal shutdown (e.g., from signal handler)
engine.stop();
// Or programmatically
void gracefulShutdown() {
// Stop accepting new orders
executor->stop();
// Stop connectors (no new market data)
for (auto& conn : connectors) {
conn->stop();
}
// Stop buses (drains queues)
tradeBus->stop();
bookBus->stop();
execBus->stop();
// Stop strategies
strategy->stop();
}
Shutdown order:
- Stop connectors (no new data)
- Drain event buses
- Stop strategies
- Complete in-flight orders
- Clean up resources
Complete Example¶
#include "flox/flox.h"
int main() {
// 1. Registry
SymbolRegistry registry;
registry.registerSymbol("binance", "BTCUSDT");
// 2. Core components
auto tradeBus = std::make_unique<TradeBus>();
auto bookBus = std::make_unique<BookUpdateBus>();
auto execBus = std::make_unique<OrderExecutionBus>();
// 3. Executor and connector
auto executor = createExecutor(registry);
auto connector = createConnector(registry, *tradeBus, *bookBus);
// 4. Strategy
auto strategy = std::make_unique<MyStrategy>(executor.get());
tradeBus->subscribe(strategy.get());
bookBus->subscribe(strategy.get());
// 5. Engine
std::vector<std::unique_ptr<ISubsystem>> subsystems;
subsystems.push_back(std::move(tradeBus));
subsystems.push_back(std::move(bookBus));
subsystems.push_back(std::move(execBus));
subsystems.push_back(std::move(strategy));
std::vector<std::shared_ptr<IExchangeConnector>> connectors;
connectors.push_back(connector);
Engine engine(loadConfig(), std::move(subsystems), std::move(connectors));
engine.start();
return 0;
}
Design Principles¶
| Principle | Implementation |
|---|---|
| Modularity | Components can be swapped independently |
| Thread safety | Lock-free constructs in hot paths |
| Zero allocation | Pre-allocated pools and ring buffers |
| Determinism | Sync mode available for backtesting |
See Also¶
- Architecture — Component overview
- Run the Demo — See integration in action
- Configuration — Configure the system