3、核心组件设计:订单管理模块(Order Manager)、行情数据模块(Market Data)、风控引擎(Risk Engine)
好,咱们直接进入正题。交易系统的三大核心组件,就像人的心脏、眼睛和大脑。缺一个,系统就转不起来。我这些年拆过不少系统,有的死在订单处理慢了,有的被行情数据淹没了,还有的干脆被风控给误杀了。今天咱们一个一个说清楚。
3.1 订单管理模块(Order Manager)
订单管理模块,说白了就是整个系统的调度中心。它负责接收客户端的下单请求,校验合法性,然后路由到对应的撮合引擎。我见过不少新手架构师,一上来就把订单逻辑和撮合逻辑混在一起写,结果后期改一个需求,整个模块都得重构。
- 订单校验(价格、数量、账户余额、持仓限制)
- 订单路由(根据交易对、市场类型分发到不同撮合引擎)
- 订单状态管理(New、PartiallyFilled、Filled、Cancelled、Rejected)
- 订单持久化(写入数据库,保证不丢单)
我个人习惯把订单管理模块设计成无状态的服务。为什么?因为无状态才好水平扩展。你想想看,如果每个订单实例都维护着本地状态,一旦实例挂了,那堆订单就全丢了。我曾经在一个项目中,就因为订单状态存在本地内存里,结果服务器断电,丢了整整两分钟的订单数据。嗯,从那以后我再也不敢这么干了。
订单状态机设计
订单状态机是订单管理模块的核心。我建议用有限状态机(FSM)来管理,别用if-else硬编码。代码示例给你看看:
// 订单状态枚举
public enum OrderStatus {
NEW,
PARTIALLY_FILLED,
FILLED,
CANCELLED,
REJECTED
}
// 状态转换规则
public class OrderStateMachine {
private static final Map<OrderStatus, Set<OrderStatus>> transitions = new HashMap<>();
static {
transitions.put(NEW, new HashSet<>(Arrays.asList(PARTIALLY_FILLED, FILLED, CANCELLED, REJECTED)));
transitions.put(PARTIALLY_FILLED, new HashSet<>(Arrays.asList(PARTIALLY_FILLED, FILLED, CANCELLED)));
transitions.put(FILLED, Collections.emptySet());
transitions.put(CANCELLED, Collections.emptySet());
transitions.put(REJECTED, Collections.emptySet());
}
public static boolean isValidTransition(OrderStatus from, OrderStatus to) {
return transitions.getOrDefault(from, Collections.emptySet()).contains(to);
}
}
3.2 行情数据模块(Market Data)
行情数据模块,就是系统的眼睛。它负责从交易所接收实时行情,然后推送给各个业务模块。这里有个关键点:行情数据是高频的,每秒可能成千上万条。如果处理不当,CPU全耗在序列化和反序列化上了。
我建议用发布-订阅模式来处理行情数据。生产者只管往消息队列里塞数据,消费者按需订阅。这样解耦之后,行情模块的吞吐量能提升好几倍。
行情数据模型
| 字段 | 类型 | 说明 |
|---|---|---|
| symbol | String | 交易对,如 BTC/USDT |
| bid | BigDecimal | 买一价 |
| ask | BigDecimal | 卖一价 |
| lastPrice | BigDecimal | 最新成交价 |
| volume | BigDecimal | 24小时成交量 |
| timestamp | long | 行情时间戳(毫秒) |
这里有个细节:时间戳一定要用交易所的,别用本地时间。我遇到过因为服务器时间不同步,导致行情数据乱序的问题。你想想看,如果A交易所的行情比B交易所的行情快了2秒,那你的套利策略就全废了。
3.3 风控引擎(Risk Engine)
风控引擎,就是系统的大脑。它负责在订单执行前、执行中、执行后做各种检查。说白了,就是防止你亏到裤衩都不剩。我见过不少交易团队,策略写得漂亮,但风控一塌糊涂,最后爆仓了都不知道怎么回事。
风控引擎一般分三层:
- 事前风控:下单前检查,比如账户余额够不够、持仓上限超没超、价格是否在合理范围内。
- 事中风控:订单执行过程中监控,比如撤单率、成交率、异常交易行为。
- 事后风控:成交后分析,比如盈亏计算、风险敞口评估、压力测试。
风控规则引擎设计
我个人习惯把风控规则做成可配置的,而不是硬编码。这样业务人员可以随时调整参数,不用等开发排期。举个例子:
// 风控规则配置(JSON格式)
{
"rules": [
{
"name": "单笔最大金额",
"type": "PRE_TRADE",
"condition": "order.amount > 100000",
"action": "REJECT",
"message": "单笔订单金额超过10万,已拒绝"
},
{
"name": "日内撤单次数限制",
"type": "MID_TRADE",
"condition": "cancelCount > 50",
"action": "FREEZE_ACCOUNT",
"message": "日内撤单次数超过50次,账户已冻结"
}
]
}
核心组件交互流程
这三个组件不是孤立的,它们之间需要紧密配合。我画了一张图,帮你理清它们的关系:
你看这张图,订单管理模块和风控引擎是双向交互的。下单前先问风控:这单能不能接?风控说行,订单才往下走。行情数据模块则像个广播站,把实时数据推送给所有需要的人。
好了,核心组件设计就讲到这里。记住一句话:订单管理要稳,行情数据要快,风控引擎要狠。这三者配合好了,你的交易系统才能扛得住市场的惊涛骇浪。