欢迎光临
我们一直在努力

你的告警系统可能在凌晨 3 点,叫用户挂出一张注定亏损的反向单

先讲一个真实复盘里出现过、让人后背发凉的事故——

某夜系统在凌晨时段对一只标的发出"止损建议"告警。问题在于:该标的对应的推荐已经在 30 余天前自然失效,但持仓追踪表没有及时清理,仍然把它视为"被关注中"。如果用户在半睡半醒状态下根据这条告警挂出反向单,造成的损失将完全由这条错误告警买单。

更刺眼的是事后排查的结论——整个推送链路在工程上都"合法":触发器逻辑没错、数据接口没错、推送通道没错。错的只是缺少了一道"这条告警在今天是否仍然成立"的校验。

这是量化选股系统开发公开课的第 3 课——告警系统该怎么不吓人。

一、为什么告警系统值得单独做产品设计

几乎所有交易系统都有告警功能。但很少有团队认真思考过"告警系统本身的产品设计"。多数情况下,告警就是一段堆在策略代码末尾的"if 触发就发邮件"。

这种简陋做法在用户量小的时候不会出大问题,但用户增多、告警增多之后,问题会以两种方式集中爆发——

  • 用户被海量推送淹没后,练就"对推送视而不见"的习惯,关键告警反而被埋没
  • 错误触发的告警在错误的时间出现,引导用户做出错误的决策

这一课的目标,是让你的系统在用户不便查看时也能让他放心信任。

二、"告警"与"通知"是两件事

这是整门课最容易被忽略、却最关键的一条区分——

通知(Notification)告警(Alert)
本质 “知会” “必须立即知晓”
错过的代价 可错过、可批量阅读、可静默 错过会带来真实损失
送达要求 不要求实时 必须第一时间唤起用户

如果两者共用同一个推送通道、同一种音效、同一套阈值,用户最终会以"通知"的标准对待所有消息,告警的紧急性被彻底稀释。

告警与通知,必须从渠道、音效、阈值、静默策略全部分开。

三、告警的"时间血统"

每一条告警在被用户看到时,应当能够回答三个时间问题——

@dataclass
class Alert:
payload: dict
trigger_time: datetime # 触发时间:告警逻辑判定"该发"的那一刻
data_time: datetime # 数据时间:判定所基于的数据对应的实际市场时间
source_event_time: datetime # 上游事件时间:引发判定的原始市场事件发生时间

这三个时间戳合起来,构成告警的**“时间血统”**。

缺少血统的告警,在事后无法追溯,也无法判定它是否仍然有效。 一条凌晨送达的告警,如果你不知道它的数据时间是几点、上游事件发生在何时,你根本无法判断"现在按它操作还来不来得及、还成不成立"。

四、去伪存真——触发与送达之间的独立校验层

告警从触发到送达之间,必须经过一道独立的校验层。

这道校验层的作用不是判断"该不该发"——那是触发层的工作——而是判断"现在发出去是不是仍然合理"。

def should_deliver(alert) > bool:
# 校验层不重新判断"该不该触发",只判断"现在送达是否仍然合理"
if not user_still_holds(alert): # 用户是否仍然持有该标的?
return False
if not data_still_fresh(alert): # 数据是否仍然新鲜?
return False
if sent_same_recently(alert, mins=5): # 最近几分钟是否已发过同样内容?
return False
return True
# 任何一条不通过 → 告警被吞掉或降级

触发层回答"是否符合条件",校验层回答"此刻送达是否还成立"——两者职责必须分离。

五、分时段管控——深夜的门槛必须更高

同一类告警,在盘中、盘后、深夜的"重要性"是不同的——

  • 盘中 / 盘后:用户可以快速响应,门槛可以适度宽松
  • 深夜:用户往往无法立即响应,半睡半醒的判断力反而会造成错误操作

THRESHOLD = {
'intraday': 1.0, # 盘中:基准门槛
'after': 1.2, # 盘后:略升
'overnight': 3.0, # 深夜:门槛显著抬高,宁可漏报
}

合理的告警系统会让深夜门槛显著高于盘中。宁可漏一点信号,也不要让用户半夜被错误告警吵醒之后,做出不可挽回的决策。

六、三个最常见的误区

误区一:“触发就发,越实时越好”

"实时"听起来很专业,但在告警这种"打扰用户"的场景里,过度实时反而是缺点。没有校验层的直发,会让所有触发器的瑕疵都直接到达用户,信任被一次又一次的误报消耗殆尽。

误区二:“告警和通知合并发,省事”

两者合并最大的代价不是工程上的混乱,而是用户认知上的麻木。一旦用户养成"反正都在同一通道,我不会立即看"的习惯,真正紧急的告警就失效了。

误区三:“加个去重就解决了”

去重只能解决"同一条告警重复推送"的问题,无法解决"在错误时机推送了正确的告警"或"基于过期数据推送了已不再成立的告警"。这两类才是更难处理、伤害更大的场景。

七、一个脱敏案例:那条凌晨的"止损建议"

某夜系统在凌晨时段对一只标的发出"止损建议"告警。问题在于——该标的对应的推荐已经在 30 余天前自然失效,但持仓追踪表没有及时清理,仍然把它视为"被关注中"。

如果用户在半睡半醒状态下根据这条告警挂出反向单,造成的损失将完全由错误告警买单。事后排查发现,整个推送链路在工程上都"合法"——触发器逻辑没错、数据接口没错、推送通道没错——错的只是缺少了一道"这条告警在今天是否仍然成立"的校验。

这次事件后我们引入了去伪存真层:所有告警在发出前必须经过一轮"现实校验",校验项包括持仓状态、数据新鲜度、最近是否已发同类告警等。这道关上线后,类似事件再没发生过。

八、思考题

  • 整理你过去 7 天收到的所有告警,对每一条标注:①是否真正需要立即处理;②是否在最佳时机送达;③是否携带足够元信息让你判断真伪。
  • 列出你系统里的告警类型,逐条评估它们应属于"告警"还是"通知"。如果两者混在同一通道,列出迁移方案。
  • 想象最坏场景:你的告警系统在凌晨 3 点向用户推送了一条错误信号,用户照做并蒙受损失。请反推:架构上应当在哪一道关把它拦下来?
  • 总结

    • 告警和通知是两件事,必须从渠道到策略全部分开
    • 每条告警都需要"时间血统"——无血统的告警不可追溯,也不可信赖
    • 触发器和推送之间必须有独立的校验层,做"现在发出去是否合理"的判断
    • 深夜告警门槛必须高于盘中——宁可漏一些,也别错一些
    赞(0)
    未经允许不得转载:171主机测评 » 你的告警系统可能在凌晨 3 点,叫用户挂出一张注定亏损的反向单
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址