第一章:订单簿基础

什么是订单簿?

订单簿,说白了就是交易所后台的那本「大账本」。它实时记录着所有交易者挂出的买卖意愿——谁想买、谁想卖、什么价格、多少数量。

我刚开始接触高频交易系统时,总觉得订单簿就是个简单的价格列表。后来在FPGA加速项目里踩过坑才明白:订单簿是整个交易系统的数据中枢。所有策略决策、风控逻辑、行情推送,最终都要落到订单簿上。

举个例子,你在股票软件上看到的「买一」「卖一」价格,就是订单簿最顶层的两条记录。但底层的数据结构远比这复杂——它需要支持每秒数万次的增删改查操作。

核心要点:订单簿 = 买方队列 + 卖方队列,按价格优先、时间优先原则排序。

限价单 vs 市价单

这两种订单类型,是交易系统里最基础的概念。我见过不少新手把两者搞混,结果在实盘里吃了大亏。

限价单(Limit Order):你指定一个价格,只有市场达到这个价格时才会成交。比如你挂单「买入BTC,价格30000,数量1个」。如果市场最低卖价是30100,那这单就挂着,直到有人愿意30000卖给你。

市价单(Market Order):你不指定价格,系统按当前最优价格立即成交。还是那个例子,你下「买入BTC,数量1个」的市价单,系统会直接吃掉卖一价位的所有挂单。

对比项 限价单 市价单
价格控制 完全由你指定 由市场决定
成交速度 可能等待很久 立即成交
滑点风险 无滑点 大单可能产生显著滑点
对订单簿影响 增加流动性 消耗流动性

我的经验:在FPGA实现中,限价单的插入操作是最耗资源的。因为需要维护价格排序,而市价单只需要匹配最优价位,逻辑简单得多。我曾经为了优化限价单插入的流水线延迟,重构了三次排序网络。

买卖盘口与价差

盘口(Order Book Depth)展示的是不同价格档位的挂单量。买盘在左边,卖盘在右边,中间那条缝就是价差(Spread)。

价差 = 最低卖价 - 最高买价。这个数字越小,说明市场流动性越好。我记得在2017年比特币疯牛行情里,有些交易所的价差能拉到几十美元,那时候做市商简直是在捡钱。

为什么价差重要?因为它直接决定了你的交易成本。你想想看,如果你同时买入和卖出同一资产,价差就是你的亏损。高频交易策略赚的就是这个价差——在买一价买入,在卖一价卖出,吃中间那一点点利润。

避坑指南:我曾经在FPGA设计里犯过一个低级错误——把盘口深度缓存设计成单端口RAM。结果在行情剧烈波动时,读写冲突导致价差计算出现毛刺。后来改成双端口RAM + 乒乓操作才解决。嗯,硬件设计里这种细节特别容易翻车。

订单簿的核心数据结构

在软件系统里,订单簿通常用红黑树或跳表实现。但在FPGA里,我们得用硬件思维来设计。

我个人习惯用排序数组 + 链表的组合。为什么?因为FPGA擅长并行比较,排序数组可以用比较器网络快速定位插入位置。而链表则方便处理同一价格下的多个订单。

// 伪代码:FPGA中的订单簿条目
typedef struct {
    uint64_t order_id;    // 订单ID
    uint64_t price;       // 价格(定点数表示)
    uint32_t quantity;    // 数量
    uint8_t  side;        // 0=买, 1=卖
    uint8_t  type;        // 0=限价, 1=市价
    uint32_t timestamp;   // 时间戳
} order_entry_t;

这里要注意,价格用定点数而不是浮点数。浮点数在FPGA里太费资源,而且比较逻辑复杂。我一般用64位定点数,高32位表示整数部分,低32位表示小数部分。

增量更新的挑战

全量快照好理解——把整个订单簿发出去就行。但增量更新就麻烦了:你只发送变化的部分,接收端要能正确还原。

常见的增量消息类型有三种:

  • 新增(Add):新订单进入订单簿
  • 删除(Delete):订单被撤销或成交
  • 修改(Modify):订单数量变化(价格不变)

在FPGA实现里,增量更新的难点在于时序控制。你想想看,如果增量消息和全量快照同时到达,接收端该怎么处理?我见过一个方案是给每条增量消息打时间戳,接收端按时间戳排序后再应用。但这样会引入额外的延迟。

我的建议:在硬件层面,用双缓冲机制来处理快照和增量的同步。一个缓冲区接收全量快照,另一个处理增量流。等快照接收完毕,再切换缓冲区并应用积压的增量。这样既保证了数据一致性,又不会阻塞流水线。

本章知识体系

下面这张图是我自己画的,把订单簿的核心概念串起来了。你看一眼就能明白各个模块之间的关系。

订单簿核心知识体系 订单簿 买方队列 (Bids) 卖方队列 (Asks) 限价单 市价单 冰山订单 止损单 买卖盘口 (Depth) 各价位挂单量分布 价差 (Spread) 最低卖价 - 最高买价 全量快照 (Snapshot) 增量更新 (Incremental) 核心模块 买方 卖方 订单类型 盘口 价差 更新方式

这张图把订单簿拆成了几个关键模块。你从中间开始看——订单簿分买卖两方,每方都包含不同类型的订单。盘口和价差是订单簿的「快照」,而全量快照和增量更新则是数据分发的两种方式。

嗯,基础概念就讲到这里。这些内容看着简单,但要在FPGA里高效实现,每个点都能挖出不少坑。后面几章我们会深入每个模块的硬件设计细节。

专注资料整理