news 2026/10/2 17:21:23

PanWatch 数据源开发指南:实现一个 Vendor 接入新行情 API 全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PanWatch 数据源开发指南:实现一个 Vendor 接入新行情 API 全流程

PanWatch 数据源开发指南:实现一个 Vendor 接入新行情 API 全流程

【免费下载链接】PanWatchPanWatch — AI stock monitoring for A-shares, HK & US markets, powered by TradingAgents. Portfolio insights, real-time alerts & automated reports.|盯盘侠:覆盖 A股/港股/美股的 AI 盯盘、持仓分析、实时提醒与自动报告。项目地址: https://gitcode.com/GitHub_Trending/pa/PanWatch

PanWatch 是一款覆盖 A股、港股与美股的 AI 盯盘工具,它的行情、K线、资金流向等数据都来自一个可插拔的数据源层。本文带你从零走完「新增一个 Vendor 接入行情 API」的完整流程:理解架构、写抓取逻辑、注册权威清单、配置主备优先级、补齐测试,并让它在 PanWatch 的数据源页真正跑起来。

一、为什么 PanWatch 需要可插拔的数据源架构

一个行情应用最难维护的不是功能,而是数据从哪来。腾讯、新浪、东财、雅虎……每家接口的字段、编码、限流策略都不一样,而且随时可能挂掉。

PanWatch 的解法是"一条路径,两层设计":上层负责故障转移和缓存,下层每个数据源(Vendor)只管一件事——把某家 API 的原始响应解析成标准类型,内部不做任何兜底。这样新增一家源,只需要动一个文件和几行注册代码,不用改核心调度逻辑。

这套架构集中在独立包 packages/marketdata 中,零 Web/数据库依赖,可单独复用,也可嵌入任意项目。

二、PanWatch 行情抓取的整体调用链

先用一句话记住四层结构,后面每一步都对应其中一层:

层级文件职责
对象式入口client.py对外提供quotes()/klines()等 API
主备调度engine.py按优先级故障转移 + TTL 缓存 + 指标
数据源抓取vendors/一家源"怎么抓 + 怎么解析"
统一 HTTPhttp.py节流、退避重试、代理、来源标记

调用方向是单向的:MarketData → Engine → Vendor → market_get。Engine 拿到哪个 vendor,就调哪个 vendor,vendor 只用market_get发请求。你开发新源时,几乎只碰第 3、4 两层。

三、第一步:实现一个 Vendor 类(只需一个方法)

每个数据类型都有对应的标记基类,定义在 vendors/base.py:QuoteVendor(报价)、KlineVendor(K线)、CapitalFlowVendor(资金流向)、EventsVendor(公告)等共 11 类。

以接入报价为例,你只需继承QuoteVendor,声明三样东西:

  • name:注册名,要和后续配置里的vendor字段完全一致;
  • supports_markets:支持的市场集合,{"US", "HK"};
  • fetch(symbols, config):唯一的抽象方法,返回标准类型列表。
class SinaQuoteVendor(QuoteVendor): name = "sina" supports_markets = {"US", "HK"} def fetch(self, symbols: list[Symbol], config: dict) -> list[Quote]: # 拼接 URL → market_get 抓取 → 解析成 Quote 列表

完整可运行的参考实现是 vendors/sina.py(新浪美股/港股备源)。注意fetch的约定:失败要抛异常(Engine 会捕获并转移),空结果返回[],不要自己写 fallback。

四、第二步:用 market_get 发请求,节流重试都内置了

不要自己import requests。PanWatch 提供了统一工具 http.py 里的market_get,它一次帮你解决了四件脏活:

  1. 按 host 节流(min_interval_s)——避免打爆同一接口;
  2. 退避重试(retries)——带抖动的指数退避;
  3. 代理支持(trust_env/proxy)——遵循系统代理设置;
  4. 编码与解析(encoding="gbk"、parse="json")——自动解码。
text = market_get( _URL + list_param, host_key=_HOST, # 节流用的主机标识 headers=_HEADERS, # 部分源必带 Referer + UA parse="text", encoding="gbk", # 新浪响应是 GBK 编码 retries=2, timeout=8, log_label="新浪报价", )

抓回来的text再解析成标准 dataclass(字段定义见 types.py,如Quote、Bar、CapitalFlow)。市场代码统一用Symbol值对象 symbol.py 归一化,别再到处手写前缀逻辑。

五、第三步:把新 Vendor 注册到权威清单

这是最容易被漏掉的一步。registry.py 里的VENDOR_CLASSES_BY_TYPE是type → vendor 的唯一真相源:

VENDOR_CLASSES_BY_TYPE = { "quote": { "tencent": TencentQuoteVendor, "sina": SinaQuoteVendor, # 👇 新增一行即可 }, }

往对应数据类型下加一行"<你的name>": <你的Vendor类>就完成了。为什么强调它是"唯一真相源"——因为PACKAGE_VENDORS_BY_TYPE(合法 vendor 名集合)和MarketData里 Engine 的vendors={}都由它自动派生,不会出现"改了引擎忘了改权威表"的漂移。

六、第四步:通过 ConfigProvider 配置主备优先级

注册只是"能用",优先级决定"谁先被调"。Engine 会按priority从小到大尝试 vendor,第一个成功且非空的就返回并缓存,全失败才返回空——这就是 PanWatch 的主备故障转移。

配置项SourceConfig长这样(节选自 README):

字段含义
vendor你的注册名
priority越小越优先
enabled是否启用
config透传凭证/参数(token、cookie 等)

在独立使用时可用内置StaticConfigProvider;而在 PanWatch 宿主里,优先级来自数据库的DataSource表,由 marketdata_client.py 中的DbConfigProvider读取并转成SourceConfig。也就是说:给新源在数据源表里插一行、排好 priority,它就自动进主备链了,无需改代码。

七、第五步:写单元测试(monkeypatch 即可,不发真实网络)

PanWatch 的全部测试都mock HTTP,不发真实请求。套路是:monkeypatch 掉 vendor 模块里的market_get,喂一段构造好的原始响应,断言解析结果。参考 test_sina_quote_vendor.py:

def test_sina_us_quote(monkeypatch): line = 'var hq_str_gb_aapl="' + "..." + '";' monkeypatch.setattr(sv, "market_get", lambda *a, **k: line) out = sv.SinaQuoteVendor().fetch([Symbol.parse("AAPL", "US")], {}) assert out[0].current_price == 150.5

在 packages/marketdata 下跑python -m pytest -q全绿即可,无需联网。

八、让新数据源跑起来:PanWatch 宿主接线与验证

代码合并后,宿主是单一路径:进程级单例get_market_data()持有一个MarketData(config=DbConfigProvider()),各 collector / Agent 直接调用它取数,没有灰度 flag、没有回退分支。

上线建议按这个顺序自查:

  1. 跑单测:pytest -q保证解析正确;
  2. 核对字段:在「数据源」页对新增的(type, provider)点「测试」按钮,看真实返回是否符合预期;
  3. 看健康度:health()会把每个 vendor 的成功率、p50 延迟、最近错误喂到健康度面板,一眼看出新源是否稳定;
  4. 调优先级:若新源更稳,把它的priority调小,让它晋升为主源。

九、常见坑与最佳实践

  • 市场要对齐:supports_markets留空 = 全市场,否则 Engine 会按市场过滤掉不支持的请求;
  • 可选依赖惰性 import:像yfinance这种三方库,务必放在fetch()内部import,不要在模块顶层引入,避免拖慢启动;
  • 失败要抛、空要返回:fetch内不要自己吞异常做 fallback,交给 Engine 统一转移;
  • 编码别猜:GBK/UTF-8 用encoding=显式声明,别靠resp.text自动探测。

小结

接入一个新行情 API 在 PanWatch 里就是五步走:继承对应*Vendor实现fetch→ 用market_get发请求 → 在registry.py权威清单加一行 → 配置priority进主备链 → 补一个 mock 单测。得益于"抓取与调度分离"的架构,你只写最薄的一层,故障转移、缓存、限流、指标全由 Engine 与market_get兜底,新源即可无缝服务 A股、港股与美股的盯盘、提醒与自动报告。

【免费下载链接】PanWatchPanWatch — AI stock monitoring for A-shares, HK & US markets, powered by TradingAgents. Portfolio insights, real-time alerts & automated reports.|盯盘侠:覆盖 A股/港股/美股的 AI 盯盘、持仓分析、实时提醒与自动报告。项目地址: https://gitcode.com/GitHub_Trending/pa/PanWatch

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 17:19:49

从 PowerSim 看可微物理仿真:当渲染原语直接变成物理粒子

从今天觉醒,技术赋予每一个人数字生命从 PowerSim 看可微物理仿真&#xff1a;当渲染原语直接变成物理粒子 ① 技术背景&#xff1a;可微渲染之后&#xff0c;下一个缺口是"可微动力学" 过去几年&#xff0c;NeRF 与 3D Gaussian Splatting 把"从照片重建三维场…

作者头像 李华
网站建设 2026/10/2 17:14:16

浙江温州优质的车载负离子发生器生产厂,排名前五广受好评

浙江温州及周边地区值得关注的车载负离子发生器生产厂家推荐&#xff0c;这五家口碑实力俱佳 随着新能源汽车保有量快速攀升&#xff0c;车内空气质量成为越来越多车主和车企关注的焦点。车内空间密闭&#xff0c;甲醛、苯等挥发性有机物、烟味、异味以及PM2.5颗粒物长期困扰驾…

作者头像 李华
网站建设 2026/10/2 17:13:56

钱财从布施中得

钱财从持不偷盗戒&#xff0c;财布施&#xff0c;法布施中得。偷盗得贫穷果报&#xff0c;坑人不富&#xff0c;赖人长穷。穷没有扎下根的&#xff0c;富没有留下苗的。积德行善&#xff0c;积善之家必有余庆。多积善因&#xff0c;必得善果。钱财从布施中得。

作者头像 李华