SKILL:基于 Wind Excel 插件的金融数据获取
- 2026-09-21 13:28:33
SKILL:基于 Wind Excel 插件的金融数据获取AI 调教专栏 各位好,我是清如。 经常要用 Wind 的人都知道,取数是家常便饭。只是这条路其实不太好走:Wind MCP 的免费额度,一个稍微像样的任务跑完就见底;想用 Wind API,光申请那一套流程就够折腾的。绕来绕去,能长期稳定用下来的,只剩那个一直躺在 Excel 里、平时没人正眼看的 Wind 插件。 可都这个年头了,还靠一只手在 Excel 里点、复制、粘贴地取数,我自己都觉得说不过去。这份手册就是为这件事写的。 说明:本手册基于Wind 终端的 Excel 插件实测整理,函数名和安装路径以你的 Wind 版本为准。 01先想清楚:为什么偏偏是 Excel 插件 Wind数据获取其实有好几条路,只是各有各的现实问题。Wind MCP 免费额度少,一个稍大的任务就耗尽,更适合偶尔查几个数;Wind API 得有正式接口,申请流程又麻烦;手工取数当然能取,但它不可复现、占时间,还照样吃配额。几条路走下来,能既不求人、又能被脚本驱动的,就只剩 Excel 插件了。
所以结论并不复杂:如果你只是偶尔取几个数,MCP 或者手工就够了;但只要你像我一样,每月固定要取几十上百个指标,就值得把插件这条路搭起来。它未必是最快的,却是你手上唯一不用申请、也不额外花钱的通道。 02环境与调用骨架 动手之前先确认两件事:本机装了 Wind 金融终端和 Excel,Python 环境里备好 xlwings、pywin32、openpyxl。xlwings 负责驱动 Excel,pywin32 用来调 COM 接口,openpyxl 留着读写落盘。这几样齐了,后面就顺了。整个自动化的骨架其实很短,两条取数路径都围着它转: 要点只有三个:Excel 在后台开起来、Wind 加载项确保启用、请求写进去之后等返回再读值。前两个是准备动作。第三个最容易被忽略——插件是异步取数的,CalculateUntilAsyncQueriesDone 会一直等到所有请求返回;你不等它算完就去读,读到的就是一片空白。所以那个循环不是多余的,是必须的。 03路径 A:股票、截面与财务(UDF 公式法) 这一类最好办,插件吃的本来就是公式。常用的就三个函数,覆盖了绝大多数取数场景:
用法和写普通 Excel 公式没区别:把公式塞进单元格,插件会异步回填。第一个参数是要取的标的,可以是单个代码,也可以是逗号分隔的一串;第二个是字段列表,比如收盘价 close、滚动市盈率 pe_ttm、市净率 pb_lf、总市值 mkt_cap_ard;第三个是参数串,可以什么都不写,也可以用来限定日期。 真正要留意的是返回布局——WSD 每行一个交易日,第 1 列是日期,后面按字段顺序排;WSS 每行一个标的,而且没有表头行、也没有名称列,你得按输入代码的顺序对齐,或者干脆把 sec_name 也放进字段里,用名字来核对。刚上手的时候,可以拿一组已知数据验一下:沪深300指数在 2026-08-03 收 4543.1781,贵州茅台那一刻的滚动市盈率是 19.54,对得上就说明通道是通的。 还有一个坑:插件会把你写的公式自动改写,在后面追加布局参数(类似 "cols=3;rows=21")。所以读结果的时候,要按它返回的整块区域去读,别按你写的公式原样去推断行列数——它返回的行列,往往和你写的不一样。 04路径 B:宏观 EDB(批注配置法) 宏观指标是另一套体系,也是创造这个skill的时候卡住的地方。你可能试过在单元格里写 =EDB(...),然后发现它恒返回空——因为 EDB 压根不走普通公式,它用的是「对话框取数 + 外链工作簿」:落表公式写成 =[1]!edb(),外链指向 Wind 安装目录下的 WindFunc.xla。这层绕,但摸清之后就是一劳永逸。 真正的取数请求不在公式里,而藏在单元格的批注里。批注内容是一段 base64,解开来是 zip 片段,里面是 8 字节二进制头加一段 JSON: 把这层结构看明白,后面的坑就都好懂了。metric 是你要取的指标列表,每一项有代码、名称、频率和一个唯一 key;timeFrameSetting 规定了取数的起止时间,格式是年月日。其中 freq 是频率枚举,日频是 1、季频是 5、月频是 6——填错,取回来的序列就完全对不上轴。最实用的一点是:一个配置里可以塞多个指标,一次刷新全部取回,这也是省配额的关键,别一个指标刷一次。刷新是能自动化的:脚本用 COM 调 CalculateFullRebuild,等它算完再读。 输出布局很规整:A1 是 Wind,第 2 行是各指标名,第 3 行起是日期和数值,一列对应一个指标。不过这一步有三个坑,我踩过其中两个:
05取数节流:把配额省下来 Wind 有取数配额,超量当天失效。所以"能取"只是及格,真正要琢磨的是怎么"省着取"。我给它加了三层节流,缺一不可。 第一层是本地缓存。取过的数据直接写进一个 JSON 文件,下次先查缓存,命中的就完全不碰 Wind;这个文件本身就是你的取数底稿,随时能回溯。取数前的计划阶段会把所有指标分成三类——缓存里已经有的、需要新取的、判定停更的,只有第二类才真正发起请求。第二层是增量补取,只对缺数据的指标发请求,obsFrom 设成最早的那个缺口月份,而不是整段重取。第三层是停更冻结:某个指标连续两次取数的末月都没变化,就判定数据源停更,记进 meta.frozen,之后自动跳过,不再浪费配额去问它。 效果是实打实的。58 个宏观指标,第一次跑全量要 33 秒;第二次直接全命中缓存,3.3 秒,零取数,配额一分没动。 有两个细节必须注意。一是期末要动态取「上一个月」——宏观月度数据滞后一个月发布,你要是写死当月,缓存永远判定有缺口,每次都会重新取,节流就白做了。二是停更判定的阈值要用 stale(默认 1 个月),别写死 12 个月,否则停更的指标永远筛不出来。 06指标代码与名称:怎么拿到、怎么核 EDB 最烦人的不是取数,是搞清楚每个代码到底代表哪个指标。代码表网上到处都有,但错的也不少——我核过一版第三方表,96 个代码里就有 7 个是错的。所以得有几条自己的路子。 相对可靠的有三条。一是官方名回收:在 Excel 用 EDB 对话框选一批指标取数,插件会把官方指标名写进批注,扫一遍历史 xlsx 就能回收,不额外消耗额度,我这样攒下了三百多条官方名。二是界面滚动 OCR:EDB 界面全选,滚动截屏加 OCR,一次能提八九百条,代码列几乎 100% 准,可惜中文名有 5~10% 的错字,拿到后要人工筛一遍。三是EDB 搜索框查代码,这条最可靠,拿到的还带来源机构和频率,值得单独说。 在 EDB 顶部搜索框输入指标代码,左侧指标列表第一行马上就会显示它的官方全名、来源机构和频率。手查几个当然没问题,但要一次查几十上百个,就得让它自动跑。脚本的逻辑不复杂:给窗口设焦点、把代码写进搜索框、读取左侧第一行的结果并落盘。听着简单,实际上是三个坑叠在一起,缺一个就完全不工作:
这三个坑排查起来,有个笨办法很管用:先用记事本做基准测试,区分是你的代码有问题,还是目标窗口根本不收键。上面两个坑就是这么揪出来的。跑通之后,M0000020 一查,返回的就是完整官方全名——"中国:工业增加值:规模以上工业企业:煤炭开采和洗选业:当月同比",比 OCR 那个被截断的名字清楚得多。靠它,我一口气补齐了五十多个名称质量差的代码。 顺带说一句:WindPy 拿不到 EDB 指标名称。当然也可能是我没找到。 07口径核验:名字会骗人 即便代码和名字都对上了,口径也未必对。我通常用三类证据交叉判断。一是看量级,利率出现两位数、PMI 超过 100,必然有错。二是看变化次数,取 5 年序列数相邻值的变化次数——0 次说明序列已停更,50~80 次差不多是月频或季频被填到了日轴上,1000 次以上才是真正的日频。三是看内部勾稽,比如三次产业加总应该等于 GDP,M1 增速通常低于 M2,国债 1 年、5 年、10 年利率应该单调递增。 由此还能总结出四条自动判错的硬规则:比值型指标出负数或大于 100;利率、同比出现两位数以上;36 期数值完全恒定;两个不同代码逐期数值完全相同。我自己就吃过亏,有个指标叫"社零当月同比",取回来其实是"当月值";"基建累计同比"实为年度值;"进/出口金额"实为当月同比。名字张冠李戴的,不止一两个,取完数花十分钟验一下,比拿错数去写东西划算得多。 08月度流程与边界 跑顺之后,日常其实很简单,一个月就三步:第一次把全量跑一遍,建好含全部目标指标的缓存;之后每个月直接跑增量脚本,只补上月的缺口,其余全部命中缓存;如果新增了指标,把它加进映射表,重跑一次数据转换脚本,再跑增量取数就行。第一次搭的时候,顺序建议是:先确认环境,用路径 A 取一条行情把通道验通,再上路径 B 啃宏观,最后把缓存节流接上。 最后是几条边界,提前知道能少走弯路。配额方面,超量当天失效,所以缓存和增量不是可选项,而是必需品。实时函数 WSQ 收盘后没有数据,别拿它做盘后快照。要是某个指标突然停更,先去数据源那头确认,别急着改脚本。还有,缓存文件就是你的取数底稿,要留着、要能回溯。 至于 WindPy,如果你要是公司有正式的 API 或者 WindPy,直接用就是,比这套省事得多——我只是没这个条件。 写到这儿,回头看这套东西,技术含量其实不高。真正磨人的是那些坑——EDB 的批注结构、查名时的输入法和坐标偏移,没有一个是靠聪明绕过去的,都是一个个撞出来的。我把它们都写在这儿了,你照着走,至少能少撞几次。 比脚本本身更值得说的,是省下来的那些时间。一个月省下的那几个小时,听着不多,攒一年也是好几十个小时,都是从机械点击里一点点抠出来的。 "并非我们的生命太短,而是我们浪费的时间太多。" —— 塞内加《论生命之短暂》 重复劳动本就不该耗在人身上。机器能做好的,交给机器;省下来的时间,留给机器替不了的事——判断、取舍,还有把数据背后的意思讲清楚。 能被机器接走的活,就别让它再占着人。 Gong Zhu De Bai Cai
import time, xlwings as xw
app = xw.App(visible=False, add_book=False) # 后台跑,可见性不影响取数
app.display_alerts = False
for a in app.api.AddIns2: # 确保 Wind 加载项已启用
if "WindFunc" in str(a.Name) and not a.Installed:
a.Installed = True
time.sleep(2)
wb = app.books.add()
sht = wb.sheets[0]
# 在这里写取数公式,或写 EDB 批注配置
for _ in range(25): # 等异步取数返回
app.api.CalculateUntilAsyncQueriesDone()
time.sleep(1.5)
# 从单元格里读取结果
wb.close()
app.quit()
头(必须字节一致):
45 44 42 00 0a 00 00 00 # 即 "EDB\x00\n\x00\x00\x00"
{
"metric": [
{"code": "M0000545", "name": "工业增加值", "freq": 6, "key": "<uuid>"}
],
"timeFrameSetting": {
"periodType": "ptObsBetween",
"obsFrom": "20221201",
"obsTo": "20260820"
}
}
本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。