第十一章:做市商系统架构

做市商系统,说白了就是一台「抢钱机器」。

我入行那会儿,带我的老大哥说过一句话,我一直记着:「你的系统比别人慢1毫秒,你就得比别人多亏1%的利润。」这话听着夸张,但干过这行的都懂——在高度竞争的做市领域,延迟就是真金白银。

这一章,咱们聊聊系统架构的核心。不扯虚的,全是实战中摸爬滚打出来的经验。

11.1 低延迟系统设计:从网线到成交的每一微秒

先问个问题:一笔订单从你的策略发出,到交易所确认成交,中间经历了什么?

我拆解给你看:

  1. 策略计算(CPU处理)
  2. 内存拷贝(数据从用户态到内核态)
  3. 网卡发送(协议栈封装)
  4. 网络传输(光纤/微波)
  5. 交易所撮合引擎处理
  6. 回包接收(同样的路径反向走一遍)

每一步都有延迟。我见过太多团队,花大价钱优化了策略,结果发现瓶颈在网卡驱动上。

核心原则:延迟优化的目标是「确定性」,而不是「快」。稳定在10微秒,比偶尔1微秒、偶尔100微秒要强得多。

11.1.1 硬件选型

我个人习惯,做市商服务器首选Intel Xeon系列,主频要高,核心数反而不是关键。为什么?因为做市策略通常是单线程的,多核并行反而引入锁竞争。

内存呢?DDR5?别急着上。我踩过坑——DDR5延迟比DDR4高,虽然带宽大,但做市商要的是低延迟,不是高吞吐。

组件 推荐配置 避坑点
CPU Intel Xeon W-3175X / AMD EPYC 7F72 别选低主频的服务器U
内存 DDR4-3200 CL14 DDR5延迟更高,慎用
网卡 Solarflare X2522 / Mellanox ConnectX-6 必须支持用户态协议栈
硬盘 Intel Optane P5800X NVMe SSD延迟还是高

小技巧:BIOS里关闭超线程、关闭CPU节能模式、关闭C-State。这些设置能稳定降低20%-30%的延迟抖动。

11.1.2 软件优化

操作系统层面,我推荐用Linux内核的RT(实时)补丁,或者干脆用DPDK绕过内核。你想想看,每次系统调用都要上下文切换,这成本太高了。

代码层面,注意几点:

  • 避免动态内存分配(用对象池)
  • 避免锁(用无锁队列)
  • 避免虚函数(减少间接跳转)
  • 数据对齐到缓存行(64字节)
// 伪代码:无锁队列示例
template<typename T>
class LockFreeQueue {
    std::atomic<size_t> head_;
    std::atomic<size_t> tail_;
    T* buffer_;
public:
    bool push(const T& item) {
        size_t tail = tail_.load(std::memory_order_relaxed);
        size_t next = (tail + 1) % capacity_;
        if (next == head_.load(std::memory_order_acquire))
            return false; // 队列满
        buffer_[tail] = item;
        tail_.store(next, std::memory_order_release);
        return true;
    }
};

注意:无锁队列不是银弹。我曾经在一个项目里用了复杂的无锁结构,结果调试了整整两周才发现一个ABA问题。能用简单锁的地方,别硬上无锁。

11.2 事件驱动架构:让系统「活」起来

做市商系统本质上是一个事件处理机。行情来了、订单成交了、风控触发了——这些都是事件。

我习惯把系统设计成「事件总线」模式。所有模块只跟总线通信,不直接调用对方。好处是解耦,坏处是……嗯,调试起来有点麻烦。

11.2.1 事件类型

  • 行情事件:Tick数据、OrderBook快照
  • 交易事件:订单确认、成交回报、撤单结果
  • 风控事件:仓位超限、资金不足、异常波动
  • 系统事件:心跳超时、连接断开、重连成功

11.2.2 事件处理流程

我画个图,你一看就明白:

行情源 交易接口 风控模块 事件总线 事件队列 事件分发器 事件过滤器 策略引擎 订单管理器 日志/监控

你看,所有模块都挂在总线上。行情来了,总线广播给所有订阅者。策略引擎收到后计算新价格,然后发一个「下单事件」回到总线,订单管理器再处理。

实战经验:事件总线一定要做「优先级队列」。风控事件优先级最高,必须立即处理。我见过一个系统,因为行情事件太多,风控事件被堵在后面,结果爆仓了。

11.3 内存数据库应用:告别磁盘IO

做市商系统里,磁盘IO是敌人。一次磁盘读写几毫秒,够行情跳好几个价位了。

所以,所有数据都放内存。订单簿、持仓、资金、策略参数——全在内存里。

11.3.1 选型对比

方案 延迟 持久化 适用场景
Redis ~100μs 支持(AOF/RDB) 策略参数、配置信息
Aerospike ~50μs 支持(SSD持久化) 用户数据、历史统计
自研内存DB <1μs 需自行实现 订单簿、持仓等核心数据

我个人倾向自研。为什么?因为Redis再快,也有网络开销。你想想看,每次查询都要走TCP/IP,这延迟受不了。

// 自研内存订单簿示例
class OrderBook {
    std::unordered_map<uint64_t, Order> orders_;
    std::map<double, std::vector<Order*>, std::greater<double>> bids_;
    std::map<double, std::vector<Order*>> asks_;
    
public:
    void add_order(const Order& order) {
        orders_[order.id] = order;
        if (order.side == BUY) {
            bids_[order.price].push_back(&orders_[order.id]);
        } else {
            asks_[order.price].push_back(&orders_[order.id]);
        }
    }
    
    // 查询最优买卖价 O(1)
    double best_bid() { return bids_.empty() ? 0 : bids_.begin()->first; }
    double best_ask() { return asks_.empty() ? 0 : asks_.begin()->first; }
};

注意:内存数据库虽然快,但一断电数据就没了。我建议做「双写」——内存里一份,同时异步写一份到Redis。这样既保证速度,又保证数据不丢。

11.4 FPGA加速基础:硬件级的极致优化

说到FPGA,很多人觉得这是「黑科技」。其实没那么神秘,说白了就是用硬件电路来实现你的逻辑。

我为什么推荐FPGA?因为CPU是顺序执行的,一条指令一条指令跑。而FPGA是并行执行的,一个时钟周期能干好多事。

11.4.1 适合FPGA的场景

  • 行情解析:交易所的二进制协议解析,FPGA可以做到纳秒级
  • 订单簿重建:增量更新,FPGA流水线处理
  • 风控检查:价格校验、数量校验,硬件级过滤
  • 信号生成:简单的策略逻辑(如价差套利)

11.4.2 一个简单的例子

假设你要做行情解析。交易所发来的数据是二进制格式,你需要解析出价格、数量、方向。

CPU做法:

// 逐字节解析
uint64_t price = (buffer[0] << 56) | (buffer[1] << 48) | ...;

FPGA做法:

// Verilog代码片段
reg [63:0] price;
always @(posedge clk) begin
    price <= {data_in[63:56], data_in[55:48], data_in[47:40], 
              data_in[39:32], data_in[31:24], data_in[23:16],
              data_in[15:8], data_in[7:0]};
end

你看,FPGA一个时钟周期就搞定了。CPU要好几条指令,还要考虑字节序。

入门建议:别一上来就搞复杂的。先从「行情解析」开始,用FPGA把行情数据解析好,然后通过PCIe传给CPU。这样CPU只负责策略计算,延迟能降一个数量级。

11.4.3 开发流程

  1. 用C/C++写算法原型
  2. 用HLS(高层次综合)转成Verilog
  3. 仿真验证
  4. 烧录到FPGA板卡
  5. 联调测试

避坑指南:我曾经花了一个月写了一个复杂的FPGA逻辑,结果仿真全对,上板就挂。最后发现是时序约束没写对。记住:FPGA开发,时序约束比逻辑本身更重要。

小结

这一章内容不少,但核心就一句话:做市商系统,延迟就是生命。

从硬件选型到软件架构,从事件驱动到FPGA加速,每一步都在跟时间赛跑。我见过太多团队,策略很牛,但系统跑不起来,最后被市场淘汰。

记住:系统架构不是锦上添花,是生存之本。


交易系统化学习资料 微信Strategy888888