一次对 V43 日线数据格式的手动逆向

前面哈里的股市API跑路了,第三方库现在又容易被封IP,于是把目光看向了一些行情软件的本地历史数据。下面是通过AI讲述的哈里分析格式的过程,最下面附上工具开源库地址。

最近在整理本地的一些历史行情数据,发现几个体积不小的 .dat 文件,路径类似 ...\ClosedDownload\Data\SHANGHAI\DayData_SH_V43.dat。文件名里的 “V43” 引起了我的兴趣——这显然是某种内部版本号。既然数据已经躺在硬盘里,不如试着看看它到底长什么样。

我用的是 HxD Hex Editor,打开沪市那个 2GB+ 的文件(实际上只有几百MB,AI幻觉),一眼扫过去全是乱码。但很快,在偏移 0x28 之后的位置,我看到了熟悉的 ASCII 字符串:600000600001……没错,就是股票代码!

这些代码每隔一段固定距离就出现一次,而且前后都有规律的二进制填充。我数了数,从一个代码到下一个,正好是 0x204 字节(516 字节)。于是大胆假设:每个股票的元数据块大小是 0x204

继续往前看,在文件最开头的几十个字节里,有几个 4 字节整数特别显眼。其中第 3 个整数的值,恰好等于我在后面数到的股票数量(比如 5200 多只)。再往后一个整数,数值很大,接近文件总 chunk 数。基本可以确定:文件头(Head)就在前 0x28 字节内,包含了股票总数、数据块总数等关键信息。

接下来的问题是:日线数据存在哪儿?

我注意到,在所有 0x204 的 code 块结束后,文件突然进入一大片结构非常规整的区域——每 40 字节一组,密密麻麻排开。尝试用 struct.unpack('<i', ...) 解析每组的前 4 字节,居然得到了像 20231012 这样的整数!这不就是 YYYYMMDD 格式的日期吗?

于是确认:每条日线记录 = 40 字节
继续解析后续字段:第 8–12 字节是开盘价(float),12–16 是收盘价……一切吻合。至此,单条日线结构基本摸清。

但新问题来了:这些日线属于哪只股票?

回到之前的 code 块,在股票代码之后、靠近尾部的位置,我发现了一连串 4 字节的整数,最后以 FF FF FF FF 结尾。这些数字看起来像是索引。而它们的数量,和该股票的日线总数除以 400 的结果一致。

灵光一现:是不是每 400 条日线组成一个“chunk”,而 code 块里存的是它所属的 chunk 索引列表?

验证了一下:文件在 code 区域之后,确实紧接着一个巨大的区域,正好被划分为 N × (400 × 40) 字节的大块。每个大块就是一个 chunk。而 code 块里的那些索引,正是指向这些 chunk 的 ID。

更妙的是,最后一个 chunk 往往不满 400 条,而 code 块里还存了一个 data_count 字段,告诉我这只股票总共有多少天的数据——这样就能精确计算出最后一块该读多少条。

整个结构豁然开朗:

[Head: 0x28]
[Code0: 0x204][Code1: 0x204]...[CodeN: 0x204]
[Chunk0: 400×40][Chunk1: 400×40]...[ChunkM: ≤400×40]

code 和 chunk 之间通过索引双向关联,既节省空间,又支持快速定位。

整个过程花了我两个晚上(差不多,用了一天),中间卡在“如何把 chunk 分配给股票”这一步很久。后来在 Qwen-Max 的帮助下理清了“索引映射”的思路,才最终把拼图完成。(实际上只是向它问了python怎么处理二进制流,以及这片小作文是它写的,还是需要人工静下心去分析结构)

写完解析器后,跑了一遍沪市数据,成功导出几千只股票的 JSON 日线。

工具本身很简单,但手动逆向一个未知二进制格式的过程,依然充满乐趣——就像解一道没有答案的谜题。

如果你也碰巧有类似的 DayData_XX_V43.dat 文件,或许这个小工具能帮上忙:
👉 https://gitee.com/harryxiaocn/daydata-v43-parser

(代码很糙,但能跑。欢迎交流,但别指望我提供数据文件 😅(这个表情有bing那味了))

—— 哈里,2025 年冬

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐