共计 2724 个字符,预计需要花费 7 分钟才能阅读完成。
为什么选择 C ++ 做量化交易?
刚接触量化交易时,很多人会用 Python 快速验证策略逻辑。但当策略真正上实盘时,你会发现:在订单成交率 99% vs 99.9% 的战场上,微秒级的延迟差异就是盈利与亏损的分界线。这时候 C ++ 的优势就凸显出来了——直接内存操作、零成本抽象、编译器优化,这些都是 Python 的 GIL 锁和解释执行无法比拟的。

核心模块实战
内存池:告别 new/delete 的性能陷阱
高频交易中频繁申请释放内存会导致两个致命问题:内存碎片增加缓存未命中率,系统调用消耗 CPU 周期。解决方案是预分配内存池:
class MemoryPool {struct Block { Block* next;};
Block* freeList_;
std::vector<void*> chunks_;
public:
MemoryPool(size_t chunkSize = 1 << 20) {allocateChunk(chunkSize);
}
void* allocate(size_t size) {if (!freeList_) allocateChunk();
auto block = freeList_;
freeList_ = freeList_->next;
return block;
}
void deallocate(void* ptr) {auto block = static_cast<Block*>(ptr);
block->next = freeList_;
freeList_ = block;
}
// ... 省略 chunk 分配实现
};
关键点:
- 每次分配固定大小内存块(适合订单对象)
- 释放时不返还系统,通过链表维护
- 实测比系统 malloc 快 5 - 8 倍
网络通信:突破 Linux 内核瓶颈
交易所 TCP 连接需要处理数万 QPS 的市场数据。传统同步 IO 模型会创建大量线程,改用 epoll 实现反应堆模式:
int epoll_fd = epoll_create1(0);
struct epoll_event ev;
ev.events = EPOLLIN | EPOLLET; // 边缘触发模式
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd, &ev);
while (running) {int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
for (int i = 0; i < n; i++) {if (events[i].events & EPOLLERR) {
// 错误处理
continue;
}
processMarketData(events[i].data.fd);
}
}
进阶技巧:
- 使用 io_uring 替代 epoll(需 Linux 5.1+)
- 绑定 CPU 核心减少上下文切换
- 预分配接收缓冲区避免拷贝
回测框架:事件驱动引擎设计
class Event {
public:
enum Type {MARKET, SIGNAL, ORDER};
virtual ~Event() = default;};
class EventEngine {
std::queue<std::shared_ptr<Event>> queue_;
std::mutex mtx_;
public:
void push(EventPtr event) {std::lock_guard<std::mutex> lock(mtx_);
queue_.push(std::move(event));
}
void process() {while (auto event = nextEvent()) {switch (event->type) {
case Event::MARKET:
strategy.onMarket(dynamic_cast<MarketEvent&>(*event));
break;
// ... 其他事件类型
}
}
}
};
性能优化实战
缓存友好编程
- 结构体按访问频率排列成员(热数据在前)
- 使用
__builtin_prefetch预取数据 - 避免虚函数(vtable 跳转破坏缓存局部性)
无锁数据结构
订单匹配场景可用无锁队列:
template<typename T>
class LockFreeQueue {
struct Node {
std::atomic<Node*> next;
T data;
};
std::atomic<Node*> head_, tail_;
public:
void enqueue(T value) {Node* node = new Node{nullptr, std::move(value)};
Node* tail;
do {tail = tail_.load(std::memory_order_relaxed);
} while (!tail_->next.compare_exchange_weak(nullptr, node, std::memory_order_release));
tail_.store(node, std::memory_order_release);
}
// ... 省略 dequeue 实现
};
使用 perf 定位热点
perf record -g ./strategy
perf report -n --stdio
关键指标:
- IPC(每周期指令数)<1.0 说明存在瓶颈
- L1-dcache-load-misses 反映缓存效率
避坑指南
浮点数精度
- 比较价格时使用 epsilon:
bool almostEqual(double a, double b) {return std::abs(a - b) < std::numeric_limits<double>::epsilon() * 10;} - 货币金额建议用整数存储(如 1.23 美元存为 123 美分)
多线程安全
- 使用
-fsanitize=thread编译检测数据竞争 - 共享数据必须用
std::atomic或 mutex 保护
API 限流处理
class RateLimiter {
std::chrono::steady_clock::time_point last_;
std::chrono::microseconds interval_;
public:
void wait() {auto now = std::chrono::steady_clock::now();
auto elapsed = now - last_;
if (elapsed < interval_) {std::this_thread::sleep_for(interval_ - elapsed);
}
last_ = now;
}
};
思考题
- 当策略逻辑复杂度上升时,如何用 C ++20 模块 / 元编程保持性能?
- 在 TensorRT 推理引擎中,怎样设计订单生成模块的接口?
- 如何用协程(C++20)简化异步 IO 代码?
(完整示例代码见 GitHub 仓库:https://github.com/example/quant-cpp-demo)
正文完
