The Goal
Build a discretionary trading platform with sub-5ms hotkey-to-order latency. When scalping, every millisecond counts.
Why C++ + ImGui?
Platform comparison reveals the decision rationale:
| Platform | Hotkey Latency | Notes |
|---|---|---|
| C++ Win32/ImGui | 1-2ms | Matches DAS Trader Pro |
| .NET WinForms | 3-5ms | Good, but not optimal |
| .NET WPF | 5-10ms | Extra render thread overhead |
| Electron | 25-50ms | GC pauses, IPC overhead |
| Web (React) | 40-80ms | Browser overhead |
The goal is to match professional platforms like DAS Trader Pro, which uses C++ with direct Win32 APIs.
Architecture
+-------------------------------------------------------------+
| ImGui + DirectX 11 |
| +----------+ +--------------+ +-------------------+ |
| | Level 2 | | ImPlot | | Position Tracker | |
| | DOM | | Charts | | + P&L | |
| +----------+ +--------------+ +-------------------+ |
+--------------------------+----------------------------------+
|
+--------------------------v----------------------------------+
| Core Engine |
| +-------------+ +---------------+ +-----------------+ |
| | Lock-free | | Frame-polled | | WebSocket | |
| | Queues | | Hotkeys | | (Boost.Beast) | |
| +-------------+ +---------------+ +-----------------+ |
+--------------------------+----------------------------------+
|
+-----------------+-------------------+
| | |
+----v----+ +----v-----+ +----v----+
| Alpaca | | Kafka | | Redis |
| API | | Consumer | | Pub/Sub |
+----+----+ +-----+----+ +----+----+
Two-Tier Hotkey System
Tier 1: Global Hotkeys (RegisterHotKey API)
- Work even when app is not focused
- Emergency actions: flatten all (Ctrl+Shift+F), panic mode (Ctrl+Shift+P)
- Latency: 1-2ms
Tier 2: Frame-Polled Hotkeys (ImGui::IsKeyPressed)
- Checked every frame at 60+ FPS (~16ms intervals)
- Trading: Shift+1 (buy), Shift+2 (sell), Shift+C (cancel), Shift+F (flatten)
- Latency: less than 1ms when app is focused
void HotkeyManager::Poll() {
auto& io = ImGui::GetIO();
if (io.WantTextInput) return; // Skip when typing
bool shift = io.KeyShift;
if (shift && ImGui::IsKeyPressed(ImGuiKey_1)) {
RecordLatency(start);
OnMarketBuy();
}
}
Built-in latency measurement using std::chrono::high_resolution_clock with running average calculation.
Lock-Free Design
Main Thread (UI) Network Threads
| |
| <--- Quote Queue ---- | Kafka Consumer
| |
| <--- Signal Queue --- | Redis Subscriber
| |
| ----> Order Queue ---> | Order Execution
Network operations run on dedicated threads to never block the UI. Uses moodycamel::ConcurrentQueue for lock-free queue implementation.
Threading Model
| Thread | Responsibility | Priority |
|---|---|---|
| Main | UI rendering, hotkey polling, order logic | High |
| Kafka | Scanner signal consumption | Normal |
| Redis | Alert subscription | Normal |
| Order Exec | REST API calls for order submission | High |
DirectX 11 Rendering
// DirectX globals static ID3D11Device* g_pd3dDevice = nullptr; static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr; static IDXGISwapChain* g_pSwapChain = nullptr; static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;
Key rendering features:
- Hardware-accelerated 60+ FPS rendering
- Double-buffered swap chain with vsync
- ImGui multi-viewport support for multi-monitor
- Dark theme with docking enabled
Memory Management
- Object pooling for quote/order objects
- String interning for symbols (one copy per symbol)
- Arena allocators for per-frame UI allocations
- No STL allocations in hot path (fixed-size buffers)
- Target: less than 50MB working set
Infrastructure Integration
Connects to existing TechsNet infrastructure:
- Kafka (10.31.11.10:9092) – market-data and scanner-signals topics
- Redis (10.31.13.50:6379) – real-time pub/sub
- MS SQL Server (sql01) – historical data, trade logging
Anti-Fat-Finger Protection
- Double-tap required for dangerous actions (flatten all)
- Modifier keys required for all trading hotkeys
- Conflict detection with system hotkeys on startup
Performance Targets
| Metric | Target |
|---|---|
| Hotkey latency | less than 5ms |
| UI frame time | less than 16ms (60 FPS) |
| Quote latency | less than 10ms |
| Memory usage | less than 50MB |
| Startup time | less than 2s |
Architectural Pivot
Initial design connected directly to Alpaca. Pivoted to use existing Kafka/Redis pipeline instead:
Alpaca WS -> Go Ingestion -> Kafka -> This platform
Quotes from Kafka market-data topic, scanner signals from scanner-signals topic. Cleaner separation of concerns.