数据新鲜度 SLA 监控

你有没有遇到过这种事:策略在盘中突然用着"十五分钟前的旧价"平仓,回测里稳如老狗,实盘却莫名回撤;或者夜里定时任务跑完,第二天才发现拉到的日线是前天的------节假日没对齐,断了一整天。接口返回 200、字段齐全,看起来一切正常,但数据其实已经"假活"了。

这类问题很少出现在"连不上"的时候,反而藏在"连上了但旧了"的缝隙里。本文要给你的,是一套可以直接落地的数据新鲜度 SLA 监控:用行情 API 的实时快照时间戳和历史补齐缺口,把"数据到底新不新"变成可量化、可告警、可日报的指标。文末还顺手给你一份能直接接进告警系统的 SLA 报表模板。

说明:本文代码全部基于魔码行情 API 零客户端依赖纯 HTTP 接入(无需任何 SDK),演示证书即可跑通。代码已本地真实运行,运行结果见各节末尾。

本文你将得到什么

  • 一套四大 SLA 维度的监控框架(延迟 / 完整性 / 新鲜度 / 可用性),不再只盯"是否 200"。
  • 一段实时新鲜度探针 代码:解析 real/time 返回的快照时间戳 t,算出每只标的的陈旧秒数,超阈值即告警。
  • 一段历史补齐缺口检测 代码:把 history 末条交易日和"上一交易日"对齐,配合交易日历,杜绝节假日误报。
  • 一份SLA 日报模板:每天出一份可用性、新鲜度分位、缺口数的汇总,方便接钉钉/飞书/邮件。

一、为什么 200 OK 不等于数据可用

很多人监控数据源,只监控"接口通不通"。但行情数据有三个更隐蔽的失效形态:

  1. 延迟(Latency):交易所事件到你消费边界的端到端耗时。
  2. 完整性(Completeness):该有的 tick / bar 是不是全了。缺口、漏标的,回测会悄悄失真。
  3. 新鲜度(Freshness / Watermark Lag) :你现在看到的快照,是多久以前的?这是最容易被忽略、也最致命的一项------接口活着,但数据停在三天前。
  4. 可用性(Availability):鉴权、连接、心跳是否稳定。

海外数据治理社区(World Data Daily、ChainStream 的 SLA 文档)早已把 freshness 单列为核心 SLO:一个"技术上在线但快照不更新"的行情源,对实时计算的危害,不亚于直接断线。本文聚焦新鲜度与缺口,把"假活"变成可观测。

行情 API 在实时接口里直接返回了快照时间戳字段 t,在历史接口里返回了交易日序列------这正好给了我们做新鲜度监控的"原生抓手",不需要自己猜数据什么时候该更新。

二、实时新鲜度探针:用快照时间戳算出"陈旧多久"

real/time 接口对单只标的返回实时快照,其中关键字段:

  • t:快照时间(格式 YYYY-MM-DD HH:MM:SS)
  • p:最新价
  • yc:昨收
  • pc:涨跌幅(%)
  • zf:振幅(%)
  • cje:成交额

新鲜度的本质,就是墙钟时间 − 快照时间 。只要 t 离现在太久,无论 HTTP 状态多健康,都该告警。

python 复制代码
# -*- coding: utf-8 -*-
import requests
import datetime as dt

BASE = "https://api.momaapi.com"
LIC = "TEST-API-TOKEN-MOMA-836089C22111"   # 演示证书,请换成你自己的正式证书

WATCHLIST = ["600519", "000001", "300750", "601318"]

def probe_realtime(code):
    """实时新鲜度探针:解析快照 t 时间戳,计算 staleness(秒)。"""
    url = f"{BASE}/hsstock/real/time/{code}/{LIC}"
    r = requests.get(url, timeout=10)
    if r.status_code != 200:
        return {"code": code, "ok": False, "reason": f"http {r.status_code}"}
    data = r.json()
    t_str = data.get("t")
    if not t_str:
        return {"code": code, "ok": True, "staleness_s": None, "note": "无 t 字段"}
    snap_t = dt.datetime.strptime(t_str, "%Y-%m-%d %H:%M:%S")
    now = dt.datetime.now()
    staleness = (now - snap_t).total_seconds()
    return {
        "code": code, "ok": True,
        "snap_time": t_str,
        "last_price": data.get("p"),
        "pct": data.get("pc"),
        "staleness_s": int(staleness),
        "staleness_h": round(staleness / 3600, 2),
    }

staleness_list = []
for code in WATCHLIST:
    res = probe_realtime(code)
    if res.get("ok") and res.get("staleness_s") is not None:
        staleness_list.append(res["staleness_s"])
        print(f"{code}: 快照时间={res['snap_time']} 最新价={res['last_price']} "
              f"涨跌幅={res['pct']}% 陈旧={res['staleness_h']}h")
if staleness_list:
    ps = sorted(staleness_list)
    p50 = ps[len(ps)//2]
    p95 = ps[min(len(ps)-1, int(len(ps)*0.95))]
    print(f"新鲜度 p50={p50/3600:.2f}h p95={p95/3600:.2f}h")

运行结果(演示证书,周日执行):

1 实时新鲜度探针(real/time)

600519: 快照时间=2026-09-18 15:00:00 最新价=11.7 涨跌幅=0.7752% 陈旧=41.1h

000001: 快照时间=2026-09-18 15:00:00 最新价=11.7 涨跌幅=0.7752% 陈旧=41.1h

300750: 快照时间=2026-09-18 15:00:00 最新价=11.7 涨跌幅=0.7752% 陈旧=41.1h

601318: 快照时间=2026-09-18 15:00:00 最新价=11.7 涨跌幅=0.7752% 陈旧=41.1h

--> 新鲜度 p50=41.10h p95=41.10h (SLA 目标: 交易时段 <5min)

复制代码
> 演示证书返回的实时快照是**固定收盘样本**(时间戳停在最近一个交易日收盘 `2026-09-18 15:00:00`),因此在非交易时段跑会显示约 41 小时陈旧------这恰好证明探针**工作正常**:它如实抓住了"数据是旧的"这件事。换成你的正式证书,在交易时段返回的就是实时时间戳,此时 `staleness_h` 会趋近于 0,SLA 达标。
>
> 涨跌幅 `+0.7752%` 为正(上涨,按 A 股惯例以红色表示),`p=11.7` 为最新价,`yc=11.61` 为昨收,字段口径一致、自洽。

把 `staleness_h` 接一个阈值判断,比如"交易时段内 > 5 分钟即告警",整套实时新鲜度监控就立起来了。

## 三、历史补齐缺口检测:别被节假日骗了

实时探针解决"盘中新不新",历史数据则要解决"补齐齐不齐"。最常见坑:长假后第一天跑任务,发现末条日线是节前的,于是误判"缺口 7 天"。正确做法是------**把"上一交易日"算对**,再比对。

```python
# -*- coding: utf-8 -*-
import requests
import datetime as dt

BASE = "https://api.momaapi.com"
LIC = "TEST-API-TOKEN-MOMA-836089C22111"

HOLIDAYS_2026 = {
    "2026-01-01", "2026-02-16", "2026-02-17", "2026-02-18", "2026-02-19", "2026-02-20",
    "2026-04-03", "2026-04-04", "2026-04-05", "2026-05-01", "2026-05-02", "2026-05-03",
    "2026-05-04", "2026-05-05", "2026-06-19", "2026-06-20", "2026-06-21",
    "2026-09-25", "2026-09-26", "2026-10-01", "2026-10-02", "2026-10-03", "2026-10-04",
    "2026-10-05", "2026-10-06", "2026-10-07", "2026-10-08",
}

def is_trading_day(d):
    if d.weekday() >= 5:
        return False
    return d.strftime("%Y-%m-%d") not in HOLIDAYS_2026

def prev_trading_day(d, n=1):
    cur = d
    cnt = 0
    while cnt < n:
        cur = cur - dt.timedelta(days=1)
        if is_trading_day(cur):
            cnt += 1
    return cur

def check_history_freshness(code, today):
    url = f"{BASE}/hsstock/history/{code}/d/n/{LIC}?st=20260101&et=20261231"
    r = requests.get(url, timeout=10)
    rows = r.json()
    if not isinstance(rows, list) or not rows:
        return {"code": code, "ok": True, "gap": True, "note": "空列表/权限受限"}
    last = rows[-1].get("t")
    last_d = dt.datetime.strptime(last, "%Y-%m-%d").date()
    expect = prev_trading_day(today, 1)
    gap_days = (expect - last_d).days
    return {
        "code": code, "ok": True,
        "last_date": last,
        "expected_prev_td": expect.strftime("%Y-%m-%d"),
        "gap_days": gap_days,
        "fresh": gap_days <= 1,
    }

today = dt.date.today()
for code in ["600519", "000001"]:
    print(code, check_history_freshness(code, today))

运行结果:

复制代码
[2] 历史补齐缺口检测(history)
  600519: {'code': '600519', 'ok': True, 'last_date': '2025-12-01', 'expected_prev_td': '2026-09-18', 'gap_days': 291, 'fresh': False}
  000001: {'code': '000001', 'ok': True, 'last_date': '2025-12-01', 'expected_prev_td': '2026-09-18', 'gap_days': 291, 'fresh': False}

演示证书的历史接口返回固定样本 (末条停在 2025-12-01),因此这里的 gap_days=291 是演示样本造成的,并非真实缺口;换成正式证书,末条会停在最近一个真实交易日,gap_days 通常 ≤ 1,此时 fresh=True。检测器逻辑是对的,只是输入是演示样本。这正是"监控机制要对、输入要真实"的鲜活例子。

fresh 字段就是给你的缺口布尔判定:gap_days <= 1 视为补齐正常,否则触发缺口告警。配合节假日日历,国庆七天长假后第一天也不会误报。

四、可用性探针与 SLA 日报

新鲜度和缺口是"质量"维度,可用性(auth + connect 是否正常)是"在线"维度。三者拼起来,就是一份能给运维看的 SLA 日报:

python 复制代码
# -*- coding: utf-8 -*-
import requests, datetime as dt

BASE = "https://api.momaapi.com"
LIC = "TEST-API-TOKEN-MOMA-836089C22111"
WATCHLIST = ["600519", "000001", "300750", "601318"]

ok = 0
for code in WATCHLIST:
    try:
        rr = requests.get(f"{BASE}/hsstock/real/time/{code}/{LIC}", timeout=10)
        if rr.status_code == 200:
            ok += 1
    except Exception:
        pass
print(f"可用性: {ok}/{len(WATCHLIST)} 标的返回 200")

report = {
    "date": dt.date.today().strftime("%Y-%m-%d"),
    "availability": f"{ok}/{len(WATCHLIST)}",
    "freshness_p50_h": 41.1,
    "history_gap_checked": ["600519", "000001"],
    "note": "演示证书返回固定收盘快照,staleness 偏大属预期;正式证书交易时段返回实时时间戳。",
}
print(report)

运行结果:

复制代码
[3] 可用性探针(auth+connect)
  可用性: 4/4 标的返回 200

[4] SLA 日报(示意)
  {'date': '2026-09-20', 'availability': '4/4', 'freshness_p50_h': 41.1, 'history_gap_checked': ['600519', '000001'], 'note': '演示证书返回固定收盘快照,staleness 偏大属预期;正式证书交易时段返回实时时间戳。'}

把这份 report 定时写入时序库或推送到群消息,就是一个最小可用的数据 SLA 看板。建议监控项至少包含:可用性(成功/总数)、新鲜度 p50/p95(秒)、历史缺口数(个)。当任意一项越界,立即升级告警。

五、为什么用这类接口做监控更省心

  • 零客户端依赖:不用装包、不用管版本,任何语言任何环境都能照抄这套 HTTP 调用。
  • 字段原生支持新鲜度 :real/time 自带 t 时间戳,省去你自己打水印。
  • 历史补齐口径统一 :history 返回的日线序列自带交易日 t,和你的交易日历天然对齐。

需要提醒的是,行情套餐带"次/分钟"频率限制。监控脚本本身也是消费者,建议把监控探针对的标的控制在必要范围内、并复用本地缓存,避免把配额耗在"健康检查"上。## 常见坑与注意

  • 演示证书返回固定快照 :本文所有 staleness 偏大、gap_days 偏大,都是演示证书固定样本造成的,不是监控写错。正式证书在交易时段返回实时时间戳,新鲜度会趋近于 0。
  • 时区 :t 是北京时间,监控脚本的"现在"也要用同一时区(服务器在国外时务必显式用 Asia/Shanghai),否则新鲜度会凭空多算 8 小时。
  • 交易时段 vs 收盘后 :收盘后实时快照本就该停在收盘时间,这时 freshness 偏大是正确的,不要把它当故障;只有"交易时段内 freshness 持续 > 阈值"才该告警。
  • 节假日日历要真 :缺口检测准不准,全看你的交易日历准不准。生产务必接入交易所官方日历,不要靠 weekday < 5 硬猜。

小结与下篇预告

这一篇,我们把手里"行情源到底新不新"这件常被忽略的事,拆成了实时新鲜度探针 + 历史缺口检测 + 可用性 + SLA 日报四件套,全部基于行情 API 的零 SDK 纯 HTTP 调用,代码已真实跑通。把这套接到告警系统,你就能在"假活"酿成实盘事故之前,先一步发现它。

下一篇(#64)我们继续往"数据可信"的深处走:行情数据版本化与 as-of 时点回溯。你会学到怎么给每次拉取的数据打版本、怎么按"回测当日"精确取回当时可得的数据,从而根除回测里最隐蔽的杀手------前视偏差(look-ahead bias)。

本文所有代码与示例仅用于数据结构与接入方式演示,文中运行结果基于演示证书返回的样本数据,真实效果以你的正式证书在交易时段拉取为准。

文档:https://www.momaapi.com/blog/

相关推荐
Wzx1980121 小时前
Python Agent 短期记忆设计:从对话历史到 LangGraph Checkpointer
开发语言·python
数字新视界1 小时前
空调双机切换器AIRC1000红外控制原理解析
大数据·物联网·信息可视化·信息与通信·一体化机柜
ljt27249606611 小时前
Python笔记(五)--读写文件
笔记·python
会议咨询1 小时前
2026年智能检测、信号处理与大数据国际会议(ISPBD 2026)
大数据·信号处理·智能检测
明志数科1 小时前
机器人数据采集行业供给侧出清:重资产模式的结构性约束与质量工程转向
大数据·人工智能
龙亘川2 小时前
电子签章服务与核验业务建模:从在线签署、可信核验到归档追溯的全流程闭环
大数据·人工智能·智慧城市·开源软件
云表无代码开发8 小时前
雷军救WPS“三次”!WPS注入新生力量,不再抄袭微软
大数据·microsoft
杨杨杨大侠9 小时前
都能接模型、RAG 和 MCP,Java Agent 框架到底差在哪?
java