C++行情交易系统通常分为‌低延迟高频交易(HFT)架构‌和‌通用量化回测/实盘架构‌

C++行情交易系统通常分为‌低延迟高频交易(HFT)架构‌和‌通用量化回测/实盘架构‌。以下剖析基于工业级实践,聚焦核心模块:行情总线、订单状态机、内存管理与线程模型。

1. 系统架构分层

典型架构采用生产者-消费者流水线,解耦网络IO与业务逻辑。

  • ‌接入层(Adapter)‌:对接交易所API(如CTP、OES)或行情源(Level-2)。负责二进制协议解析、心跳维持、重连机制。
  • ‌行情总线(Market Data Bus)‌:统一数据格式,分发Tick数据。核心要求是低拷贝、无锁分发。
  • ‌策略引擎(Strategy Engine)‌:订阅行情,计算指标,生成交易信号。需支持动态加载(.so/.dll)。
  • ‌订单管理(Order Management System, OMS)‌:维护订单状态机(New, PartiallyFilled, Filled, Cancelled),处理风控检查。
  • ‌执行层(Execution)‌:将内部订单转换为交易所特定协议发送,处理回报。

2. 核心技术实现

2.1 无锁行情总线与内存池

为避免new/delete带来的抖动和锁竞争,使用预分配内存池和无锁环形队列(Ring Buffer)。

cpp
 
#include <atomic> #include <vector> #include <cstring> // 简单定长对象池示例 template<typename T, size_t PoolSize = 1024> class ObjectPool { struct Node { T data; std::atomic<bool> in_use{false}; }; std::vector<Node> pool_; public: ObjectPool() : pool_(PoolSize) {} T* acquire() { for (auto& node : pool_) { bool expected = false; if (node.in_use.compare_exchange_strong(expected, true)) { return &node.data; } } return nullptr; // 池满,实际生产环境应阻塞或扩容 } void release(T* obj) { // 通过指针偏移找回Node,简化起见此处省略具体实现,通常需记录Node指针 // 实际生产中常用 free-list 或 boost::pool } }; // 无锁单生产者单消费者队列 (SPSC) template<typename T> class SPSCQueue { std::vector<T> buffer_; size_t head_ = 0; size_t tail_ = 0; size_t capacity_; public: SPSCQueue(size_t cap) : buffer_(cap), capacity_(cap) {} bool push(const T& item) { size_t next_tail = (tail_ + 1) % capacity_; if (next_tail == head_) return false; // 满 buffer_[tail_] = item; tail_ = next_tail; return true; } bool pop(T& item) { if (head_ == tail_) return false; // 空 item = buffer_[head_]; head_ = (head_ + 1) % capacity_; return true; } };

2.2 订单状态机

订单生命周期管理必须严谨,避免状态不一致。使用枚举和映射表管理状态转换。

cpp
 
enum class OrderStatus { New, PendingSubmit, PartiallyFilled, Filled, Cancelled, Rejected }; class Order { public: std::string order_id; std::string symbol; double price; int quantity; OrderStatus status; bool transition(OrderStatus new_status) { // 简单状态机校验,实际需更复杂的合法转换矩阵 if (status == OrderStatus::Filled || status == OrderStatus::Rejected) { return false; // 终态不可变 } if (status == OrderStatus::Cancelled && new_status != OrderStatus::Cancelled) { return false; } status = new_status; return true; } };

2.3 高性能行情解析(Zero-Copy思想)

解析二进制行情包时,尽量避免多次memcpy。若协议对齐良好,可直接映射结构体;否则使用快速字段提取。

cpp
 
#pragma pack(push, 1) struct RawTick { char symbol; double last_price; int64_t volume; int64_t timestamp_ns; //... 其他字段 }; #pragma pack(pop)‌‌:ml-citation{ref="10" appearance="aggregated" data="citationList"} void process_raw_data(const char* buffer, size_t len) { // 假设buffer包含多个RawTick,实际需根据包头长度解析 const RawTick* tick = reinterpret_cast<const RawTick*>(buffer); // 直接访问,零拷贝 double price = tick->last_price; // 注意字节序转换,如果交易所是大端而主机是小端 // price = ntohll_double(price); }

3. 关键优化点

  1. ‌CPU亲和性(Affinity)‌:将行情接收线程、策略计算线程绑定到特定CPU核心,减少上下文切换和缓存失效。
    bash
     
    # Linux下使用 taskset 绑定进程到核心 0-3 taskset -c 0-3./trading_engine
  2. ‌避免系统调用‌:日志写入、网络发送等IO操作异步化。使用mmap或共享内存进行进程间通信(如行情服务到策略服务)。
  3. ‌编译器优化‌:开启-O3,使用-march=native利用SIMD指令加速数学计算(如移动平均线计算)。
  4. ‌时间戳精度‌:使用clock_gettime(CLOCK_MONOTONIC)或CPU指令rdtsc获取纳秒级时间戳,用于计算端到端延迟。

4. 常见坑点与修复

  • ‌浮点数精度‌:价格计算严禁使用double直接比较相等。
    • 修复:使用整数表示价格(如分或毫厘),或使用std::abs(a - b) < epsilon。
  • ‌全局锁竞争‌:多个策略线程同时访问全局行情快照。
    • 修复:每个策略持有独立的行情副本,或使用读写锁(std::shared_mutex),但最好采用数据分片(Sharding),按股票代码哈希分配到不同线程。
  • ‌内存泄漏‌:高频创建临时对象。
    • 修复:全面使用对象池,禁止在热路径(Hot Path)中使用std::make_shared或new。

5. 最小可运行骨架示例

cpp
 
#include <iostream> #include <thread> #include <atomic> #include <chrono> std::atomic<bool> running{true}; // 模拟行情线程 void market_data_feed() { while (running.load()) { // 模拟接收行情 std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 推送至无锁队列... } } // 模拟策略线程 void strategy_engine() { while (running.load()) { // 从队列取行情 // 计算信号 // 发送订单 std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } int main() { std::thread md_thread(market_data_feed); std::thread st_thread(strategy_engine); // 模拟运行10秒 std::this_thread::sleep_for(std::chrono::seconds(10)); running.store(false); md_thread.join(); st_thread.join(); return 0; }

此架构适用于中低频量化及高频交易原型。生产环境需引入FIX协议解析、复杂风控模块及持久化存储(如ClickHouse/KDB+)

posted on 2026-10-31 20:00  书生居士  阅读(7)  评论(0)    收藏  举报

导航