交易事件分类标准:给系统装上「交通灯」

做量化交易这些年,我最大的体会就是:事件管理是系统的中枢神经。你想想看,一个交易系统每天要处理多少事情?订单来了、风控报警、行情跳动、系统报错...如果没有一套清晰的分类标准,那简直就是一场灾难。

我个人习惯把事件分类比作交通灯系统。红灯停、绿灯行、黄灯警示,每种事件都有它的「颜色」和「优先级」。今天我们就来聊聊这个分类标准。

按业务类型分类:四大金刚

交易系统里的事件,按业务类型可以分成四类。这四类几乎覆盖了所有场景,我在项目中遇到过不少因为分类不清导致的线上事故。

事件类型 典型场景 处理时效要求
订单事件 下单、撤单、成交、拒单 毫秒级
风控事件 资金不足、持仓超限、异常交易 微秒级
行情事件 Tick更新、K线生成、深度变化 纳秒级
系统事件 服务宕机、网络断开、数据库异常 秒级

订单事件是最核心的。说白了,你的策略再牛,最终都要靠订单来执行。我记得有一次,因为订单事件和行情事件混在一起处理,导致撤单指令延迟了200毫秒,结果错过了最佳平仓时机。嗯,从那以后我就把订单事件单独拎出来,用独立的消息队列处理。

风控事件是保命的。我曾经见过一个系统,风控事件和普通事件共用线程池,结果行情剧烈波动时,风控事件被堵在队列里出不来。最后爆仓了,风控报警才姗姗来迟。所以我现在做设计,风控事件必须走独立通道,优先级最高。

行情事件是数据源。这里有个坑要注意:行情事件量极大,每秒可能几万笔。如果处理不当,很容易把系统打垮。我的做法是:行情事件只做「轻处理」,比如更新缓存、触发信号,绝不在这里做复杂计算。

系统事件是基础设施。这类事件虽然不直接参与交易,但一旦出问题就是大事。比如数据库连接池耗尽,所有订单查询都会失败。我建议系统事件要有独立的监控告警链路。

核心原则:四种事件类型要物理隔离,不能混在一个队列里。订单和风控走高速通道,行情走专用通道,系统事件走监控通道。

按紧急程度分类:四色预警

紧急程度决定了事件的处理优先级。我习惯用颜色来标记:

  • 致命(红色):系统必须立即停止交易。比如风控阈值被突破、核心服务宕机。处理时限:< 1毫秒
  • 高(橙色):需要人工介入。比如大额订单异常、网络延迟飙升。处理时限:< 100毫秒
  • 中(黄色):自动处理即可。比如普通订单拒单、行情数据缺失。处理时限:< 1秒
  • 低(绿色):记录日志,事后分析。比如用户登录、配置变更。处理时限:> 1秒

为什么会这样分?因为致命事件一旦处理慢了,可能直接导致资金损失。我有个血的教训:有一次致命事件的处理线程被高事件阻塞了,结果风控没来得及触发,直接穿仓了。所以我现在强制要求:致命事件必须抢占式执行,哪怕打断其他任务也要先处理它。

避坑指南:我曾经把「高」和「中」的阈值设得太接近,结果线上频繁出现误报。后来我调整了策略:高事件必须满足「影响交易」且「需要人工」两个条件,缺一个就降级为中。

按影响范围分类:三圈模型

影响范围决定了事件处理的「波及面」。我把它画成三个同心圆:

全局影响 所有用户、所有策略 局部影响 特定策略、特定品种 单用户 单个账户

这个图我用了很多年。你看,最内圈是单用户,比如某个用户的订单被拒。这种事件影响最小,自动重试或者通知用户就行。

中间圈是局部,比如某个策略的所有订单都异常。这时候需要暂停该策略,但不影响其他策略运行。我记得有一次,一个CTA策略的行情源断了,我第一时间把它切到局部隔离区,其他策略照常运行。

最外圈是全局,比如交易所接口全部断开。这种事件必须立即停止所有交易,启动应急预案。嗯,这里要注意:全局事件的处理逻辑要尽可能简单,别搞复杂了,否则容易出二次事故。

我的经验:影响范围决定了「谁该知道这个事件」。单用户事件通知用户即可,局部事件通知策略管理员,全局事件必须通知所有人,包括老板。

三维分类法:组合起来用

光有分类还不够,关键是怎么组合。我推荐用三维矩阵来定义事件优先级:

// 事件优先级计算示例
function getEventPriority(event) {
  const businessWeight = {
    'order': 4,
    'risk': 5,
    'market': 3,
    'system': 2
  };
  
  const urgencyWeight = {
    'fatal': 5,
    'high': 4,
    'medium': 2,
    'low': 1
  };
  
  const scopeWeight = {
    'global': 5,
    'local': 3,
    'single': 1
  };
  
  // 综合评分
  const score = businessWeight[event.type] * 
                urgencyWeight[event.urgency] * 
                scopeWeight[event.scope];
  
  // 致命事件直接最高优先级
  if (event.urgency === 'fatal') return 100;
  
  return score;
}

你看,这样一组合,每个事件就有了唯一的「身份码」。比如一个「全局致命风控事件」,评分就是 5×5×5=125,妥妥的最高优先级。而一个「单用户低优先级系统事件」,评分只有 2×1×1=2,排到最后处理就行了。

核心思想:不要用单一维度判断事件优先级。业务类型、紧急程度、影响范围三个维度缺一不可。我见过太多系统只按紧急程度排序,结果一个「高紧急但单用户」的事件抢了「中紧急但全局」事件的资源,导致连锁反应。

好了,这就是事件分类的核心框架。说白了,就是给每个事件打上三个标签:是什么业务、有多紧急、影响多大。有了这套标准,你的交易系统就像装了交通灯,该停的停,该走的走,不会乱成一锅粥。

我个人习惯在项目初期就把这个分类标准定下来,写到开发规范里。否则等到线上出问题了再补,那代价就大了去了。


专注资料整理