4、事件类型定义:市场事件、订单事件、账户事件、风控事件、系统事件
事件驱动系统里,事件就是系统的「血液」。
我见过不少团队,一开始觉得事件定义很简单,随便搞几个枚举就完事了。结果系统跑起来之后,各种事件混在一起,调试起来简直想砸键盘。说白了,事件类型的划分,直接决定了你的系统有多灵活、多好维护。
4.1 市场事件(MarketEvent)
市场事件是最基础、最频繁的事件。它代表市场数据的更新。
我个人习惯把市场事件分成两类:
- Tick事件:每笔成交或报价的推送。频率极高,毫秒级甚至微秒级。
- Bar事件:K线数据,比如1分钟、5分钟、日线。通常是聚合后的数据。
代码里我一般这样定义:
@dataclass
class MarketEvent:
event_type: str # 'tick' 或 'bar'
symbol: str
timestamp: datetime
data: dict # 具体数据,比如价格、成交量
我的经验: 别把市场事件搞得太「胖」。我见过有人把几十个字段塞进一个事件里,结果下游每个模块都要解析一堆用不上的数据。保持轻量,只带核心字段。
4.2 订单事件(OrderEvent)
订单事件是交易系统的「动作指令」。它告诉系统:该下单了、撤单了、或者订单状态变了。
你想想看,订单事件如果定义不清楚,很容易出现「重复下单」或者「漏单」的情况。我曾经在一个项目中,就因为订单ID生成逻辑有bug,导致同一个订单被提交了两次,那叫一个惨。
我建议至少包含以下字段:
| 字段 | 说明 |
|---|---|
| order_id | 唯一标识 |
| symbol | 交易品种 |
| side | 买卖方向 |
| quantity | 数量 |
| order_type | 限价单/市价单等 |
| status | 已提交、已成交、已撤销等 |
@dataclass
class OrderEvent:
event_type: str # 'new', 'cancel', 'fill'
order_id: str
symbol: str
side: str
quantity: float
price: float
status: str
注意: 订单事件一定要有幂等性设计。同一个订单ID重复发送,系统应该能识别并忽略。否则,你可能会在实盘时「喜提」双倍仓位。
4.3 账户事件(AccountEvent)
账户事件反映的是你的资金和持仓变化。说白了,就是「钱袋子」的事。
我记得有一次,系统跑得好好的,突然账户事件里显示余额为负。排查了半天,发现是某个模块在更新账户时,没有加锁,导致并发写入把数据写乱了。从那以后,我对账户事件的处理就格外小心。
账户事件通常包括:
- 余额变动:入金、出金、盈亏结算
- 持仓变动:开仓、平仓、持仓调整
- 保证金变动:占用保证金、可用保证金
@dataclass
class AccountEvent:
event_type: str # 'balance', 'position', 'margin'
account_id: str
currency: str
amount: float
timestamp: datetime
避坑指南: 我曾经把账户事件和订单事件混在一起处理,结果订单成交后,账户更新有延迟,导致后续订单判断可用资金出错。后来我强制要求:订单事件和账户事件必须分开处理,且账户事件要保证顺序性。
4.4 风控事件(RiskEvent)
风控事件是系统的「刹车」。当交易行为触发了风控规则,就会产生风控事件。
嗯,这里要注意:风控事件不一定是坏事。它可能是提醒,也可能是强制干预。
常见的风控事件类型:
- 预警事件:比如持仓集中度超过80%,但还没到上限
- 限制事件:比如当日亏损达到阈值,禁止开新仓
- 强平事件:比如保证金不足,系统强制平仓
@dataclass
class RiskEvent:
event_type: str # 'warning', 'restrict', 'force_close'
rule_name: str
severity: int # 1-10,越高越严重
message: str
timestamp: datetime
我的教训: 风控事件一定要有「优先级」和「可恢复性」设计。我曾经遇到一个bug,风控事件触发后,系统直接停掉了所有交易,但风控条件解除后,系统没有自动恢复。结果白白错过了行情。所以,风控事件最好带一个「恢复事件」的机制。
4.5 系统事件(SystemEvent)
系统事件是系统的「心跳」和「日志」。它不直接参与交易,但决定了系统能不能稳定运行。
我个人习惯把系统事件分成三类:
- 启动/停止事件:系统启动、关闭、重启
- 错误事件:连接断开、数据异常、内存不足
- 状态事件:系统健康检查、模块心跳、配置变更
@dataclass
class SystemEvent:
event_type: str # 'startup', 'shutdown', 'error', 'heartbeat'
module: str
status: str
detail: str
timestamp: datetime
建议: 系统事件一定要有「持久化」机制。我见过有人只把系统事件打印到控制台,结果系统崩溃后,连排查问题的线索都没有。至少要把错误事件和状态事件写入日志文件或数据库。
4.6 事件关系图
下面这张图展示了五种事件类型之间的关系:
从图中可以看出:市场事件驱动订单事件,订单事件影响账户事件,账户和订单又可能触发风控事件。而系统事件贯穿始终,监控所有模块的健康状态。
核心要点: 事件类型的定义要「清晰、独立、可扩展」。每个事件只做一件事,不要搞「万能事件」。这样后期维护和扩展才会轻松。