Alpaca 券商 SSE 事件流
将以下提示词粘贴到你的 AI 对话框中:
请根据 https://skillhub.cn/install/skillhub.md,安装 @user_3c6cb52e/alpaca-broker-sse-events-fvnv。
技能介绍
解决什么问题
券商 REST 接口是请求-响应式的,你要反复轮询 activities、orders、journals、funding 等列表才能发现状态变化,既浪费配额,也带来明显的状态延迟。Alpaca 的 Broker API 提供了另一条路径:Server-Sent Events。应用只需发起一个长连接 HTTP GET,就能收到账户审核、journal 生命周期、资金划转、订单成交等事件的实时推送。
但 SSE 并不只是“少轮询”。连接会断开,进程会重启,事件会因为消费端故障而丢失。真正难的是断线后如何补数据、如何避免重复事件造成重复副作用,以及如何区分“低延迟”和“最终正确”。
技能如何工作
这个技能围绕 Broker API 的 SSE 端点组织,先按业务域选择事件流:
GET /v1/events/accounts/status:账户属性变化、account_blocked、trading_blocked、KYC 结果等。GET /v2/events/journals/status:JNLC / JNLS journal 生命周期。GET /v2/events/funding/status:Transfer、BankRelationship、WireBank、FundingWallet 等资金实体,消费时按entity_type分流。GET /v2/events/trades:new、fill、partial_fill、canceled、rejected、trade_correct等订单事件。GET /v1/events/nta:分红、利息、费用、拆股、ACAT、现金派发等非交易活动。
连接方式是普通 HTTP:发送 GET 请求,保持连接打开,逐条解析 data: {...} 帧。鉴权使用 Broker API host 与 HTTP Basic auth,和 Broker REST 相同。注意浏览器原生 EventSource 不能自定义 Authorization 头,服务端应使用支持该头的 SSE 客户端。
可靠性的核心是 replay cursor。每个流都支持按时间或 ID 回放历史:
since/until使用时间戳;since_id/until_id使用 ID。- v2 流的 ID 是 ULID;v1 账户与 NTA 流同时携带整数
event_id和event_ulid,因此可以使用since_ulid/until_ulid。 - 设置
until时必须有since;设置until_id时必须有since_id;不能混用since、since_id和since_ulid。 - 如果不提供任何
sincecursor,就不会返回历史,只会收到当前时刻之后的实时推送。
生产消费器必须持久化“最后一条成功处理的事件 ID”。每次重连时把它作为 since_id(v2)或 since_ulid / since_id(v1)传回去,让 Alpaca 回放断开期间错过的事件。只重连但不带 cursor,会把断线期间的事件静默丢弃。
事件处理建议采用快照优先的幂等流水线:先按 event_id 做 upsert 或跳过重复;更新订单、转账、journal 时对目标行加锁;按当前状态判断是否执行状态跃迁;只有在事件处理成功后才推进 cursor。这样即使出现重放或 at-least-once 投递,也不会触发重复副作用。
SSE 连接本身也需要工程化维护:跟踪最近一次收到消息的时间,静默超过阈值就主动拆线重连;失败后使用带上限的指数退避;用 flag 防止错误风暴期间并发启动多个重连;对单个事件处理加 try/catch,避免一条异常事件或下游抖动导致整条流退出。
适用边界
SSE 用于低延迟感知事件,但不等于权威状态。长时间宕机、超出保留窗口、未处理的事件类型或代码缺陷都可能导致事件消费缺口,因此必须定期执行对账:重新拉取 activities、journals、transfers 等最终状态,并做 upsert 修正。
另一个常被低估的问题是排序。ULID 在同一毫秒内包含随机成分,极短时间内的两个事件可能无法保证严格全序。对账场景下,应从最后一条事件的几分钟之前重启流,并依赖幂等处理吸收重叠,而不是假设严格顺序。
路径和版本并不统一,接入时需逐项核对:/v1/events/trades 与 /v1/events/journals/status 属于 legacy;/v2/events/trades 已由旧的 /v2beta1 重定向而来。OpenAPI 难以完整表达 SSE,由代码生成的 API 客户端可能会在这些“永不结束”的端点上挂住,应使用真正的 streaming HTTP / SSE 客户端。
各业务流也有细节差异。账户流可驱动 onboarding 与交易开通,但要拒绝在 live handler 中收到 sandbox / paper 账户 ID。订单流的 new、accepted、pending_new 属于成交前事件,成交后才应更新组合与持仓缓存。journal 流中 executed 并非终态,correct 会生成新的 journal ID。Funding / transfer 虽然统一在一个流中,但某些 funding-wallet 的 per-transfer 状态可能仍需额外轮询。NTA 事件应保存为活动快照,作为余额和组合对账输入。
最终架构建议是:SSE 负责低延迟,定期 reconciliation 负责正确性,二者缺一不可。
使用场景
- 券商后台开发要实时接收账户审核、订单成交、journal 生命周期变化,并减少对 REST 接口的轮询。
- 支付对账工程师需要根据 funding/transfer 事件确认转账状态,断线后通过 since_id 补回遗漏事件。
- 实时风控或合规工程师要消费账户 status_to 与 trading_blocked 变化,及时暂停交易或触发人工审核。
- 平台工程师需要把分红、利息、费用等非交易活动写入本地账本,并按 event_id 做幂等 upsert。
适合人员
- 券商交易平台后端工程师,需要把账户状态、订单更新和资金划转事件接入实时处理链路。
- 负责支付与资金对账的工程师,需要在 Alpaca 转账、银行关系和钱包状态变化时保持本地账本一致。
- 实时风控与合规工程师,需要根据账户状态和交易限制事件快速触发审核或交易暂停。
- 构建活动快照与组合对账系统的工程师,需要稳定消费分红、利息、费用等非交易事件并避免重复入库。