【魔码量化工程实战进阶 #07】实时行情的生产级消费:订阅推送与快照一致性
【魔码量化工程实战进阶 #07】实时行情的生产级消费:订阅、推送与快照一致性
入门系列第 03 篇讲了"实时行情字段全解读",但那是"拉一次看一眼"。本篇进入生产视角:如何让行情持续、稳定、一致地流入你的策略——本地快照怎么维护、乱序/重复怎么处理、跨日怎么重置。这是把"看行情"变成"用行情"的关键一跃。
本文你将得到什么
- 轮询 vs 长连接(推送)两种消费模式的取舍
- 本地快照(snapshot)的工程实现:一份始终最新的
code → quote映射 - 三个生产级一致性坑:跨日
yc重置 / 停牌股不更新 / 字段语义跨接口漂移 - 一个可跑的
QuoteConsumer骨架(基于真实返回的字段结构)
一、痛点:拉一次 ≠ 持续消费
回测可以"一次性把历史全读完"。但实盘/盯盘要的是"此刻全市场最新价"。新手写法:
while True:
q = get_realtime("600519")
my_strategy.on_tick(q)
time.sleep(3)
问题:① 每次只拿到一只,全市场 5000 只轮一圈要很久;② 没有"全局最新视图",策略问"现在 银行板块均价多少"答不上;③ 跨日时 yc(昨收)会变,不重置会算错涨跌幅;④ 停牌股返回的还是昨天价,你当成"没波动"会误判。
二、工程方案:本地快照 + 增量合并
核心思想:维护一份进程内"最新快照表",每次拉取只做增量合并。策略不直接调接口,而是读这份快照——解耦、快、一致。
接口 ──(定时拉取/推送)──> 快照表(snapshot[code]=quote) ──> 策略读
▲
└── 每次更新覆盖旧值,保留最新
两种拉取模式:
| 模式 | 做法 | 适合 | 注意 |
|---|---|---|---|
| 轮询 | 定时 GET 全市场/订阅列表 |
分钟级、低频 | 受限于证书 QPS(见 #03) |
| 长连接/推送 | WebSocket 订阅,服务端主动推 | 秒级、tick 级 | 需服务端支持,断线要重连+补快照 |
魔码实时行情为纯 HTTP 接口,本文以轮询 + 快照为主;若后续开放推送通道,把"拉取"换成"收推送"即可,下游快照逻辑不变。
三、可跑代码(零 SDK;演示证书标"演示数据")
下面用真实返回的字段结构(实测 510300 沪深300ETF 实时快照字段为 pe,ud,pc,zf,tr,pb_ratio,p,o,h,l,yc,cje,v,pv,tv,t)构建一个 QuoteConsumer:
import requests, time
TOKEN = "TEST-API-TOKEN-MOMA-836089C22111" # 换成你的正式证书
BASE = "https://api.momaapi.com"
class QuoteConsumer:
def __init__(self):
self.snap = {} # code -> 最新行情
self.last_day = None # 跨日重置用
def refresh(self, codes):
today = time.strftime("%Y-%m-%d")
if today != self.last_day: # 跨日:清空昨收依赖,避免涨跌幅算错
self.last_day = today
self._reset_day()
for c in codes:
try:
q = requests.get(f"{BASE}/hsstock/real/time/{c}/{TOKEN}", timeout=20).json()
if "error" in q: # 停牌/无权限:保留旧值并标记
q["stale"] = True
self.snap[c] = q # 增量覆盖,始终最新
except Exception:
pass # 单只失败不阻断(接 #04 重试更佳)
return self.snap
def _reset_day(self):
for c in self.snap:
self.snap[c]["yc"] = self.snap[c].get("p") # 昨收更新为昨日收盘
def latest(self, code):
return self.snap.get(code)
四、本机实测(真实接口返回结构)
我用演示证书拉了 510300(沪深300ETF)的实时快照,真实返回字段与样例值:
ETF实时 字段: ['pe', 'ud', 'pc', 'zf', 'tr', 'pb_ratio', 'p', 'o', 'h', 'l', 'yc', 'cje', 'v', 'pv', 'tv', 't']
ETF实时 样本: p=11.65, o=11.54, h=11.68, l=11.48, yc=11.59,
pc=0.5177(涨跌幅%), zf=1.7256(振幅%), pe=4.4, pb_ratio=0.48,
tr=0.43(换手率%), cje=成交额, v=成交量
演示证书返回演示数据,需替换为正式证书;字段语义以官方文档为准。
五、原理深挖:三个生产级一致性坑
- 跨日
yc重置:yc是昨收,涨跌幅pc=(p − yc)/yc。T 日收盘后到 T+1 开盘前,yc必须从"今日收盘"翻成"昨日收盘"。不重置,T+1 第一笔算出的涨跌幅会离谱。上面_reset_day在日期切换时把yc设为昨日p。 - 停牌股不更新:停牌股票实时接口返回的还是停牌前最后价,时间戳停在停牌日。若直接当"当前价"会误判。正确:检查返回里的
t(时间)是否过期,或接口是否返回error/停牌标记,过期则标stale不参与计算。 - 字段语义跨接口漂移(重要):同一个
pc字段,在实时接口里是"涨跌幅%"(如 0.5177),在历史 K 线接口里却是"前收"(如 11.72)。混用会直接算错。务必按接口分别解析——这正是 #12 要讲的"字段契约"。
六、小结
生产级行情消费 = 一份始终最新的本地快照 + 增量合并 + 跨日/停牌/语义三道一致性护栏。策略只读快照、不直连接口,既快又稳。这套快照是后面"指标计算(#13–#17)"和"实时风控(#21)"的直接数据源。
要维护"全市场 5000+ 只的实时快照",轮询频率与证书 QPS 是硬约束——魔码量化 Pro 包(全市场实时、更高配额)正是为此设计。详见文末。
免责声明:本文所有示例数据仅用于接口演示,不构成任何投资建议;市场有风险,投资需谨慎。
系列持续更新中。 想要亲手跑通上面的代码?前往 魔码证书申请页 免费领取你的专属证书,复制即用、按次计费、稳定可用。
