通达信本地全市场扫描
0. 前置条件(必须,缺一不可)
本技能强依赖本机通达信数据 —— 它不是能独立出结果的分析技能。
| 前置 | 说明 |
|---|---|
| 操作系统 | Windows(通达信客户端仅有 Windows 版) |
| 已安装通达信 | 默认路径 C:\new_tdx;装在别处可用 ls -d /c/*/ \| grep -iE "tdx\|zd_\|tong" 找 |
| 已下载盘后数据 | C:\new_tdx\vipdoc\sh\lday\ 下应有上万个 .day 文件。为空 → 提示用户先在通达信里做「盘后数据下载」 |
| 可选:板块文件 | 板块共鸣需要 T0002\hq_cache\block_zs.dat 等;缺失时单票形态扫描仍可跑 |
反向说明(同样重要):
- 不需要任何 API Key、不需要联网(除可选的
sync_tdx_official.py拉官方数据)—— 所有计算都在本地二进制上完成,这正是它相对 MCP 逐只拉 K 线的核心优势; - 脚本几乎零第三方依赖:生产流水线只用 Python 标准库,无需
pip install。 唯一例外是smoke_test.py(浏览器冒烟验收)需要playwright——它不参与生产链路, 只有要自动验证看板渲染时才用得上; - 不依赖 MCP 连接器做扫描。
tdx-connector之类走的是另一条路(实时/单票),本技能走本地全量; 但若做盘中实时复核(非盘后扫描),需另装 WorkBuddy 的westock-mcp(腾讯自选股) 连接器 拉实时报价/资金流——本地.day不含当日未收盘数据,盘中等级判断要联网补; - 没有通达信就用不了。此时应改走在线数据源(iFinD / westock / 东财), 或先请用户安装通达信并下载盘后数据——别硬跑,会得到空结果。
配套:算完形态要画图 / 判买点细节用
chanlun-kline。 本技能筛出候选,它负责单票结构计算与交互图——两者是「整车 vs 引擎」关系。
何时用
- 需要全市场扫描(几百只以上)→ MCP 逐只拉 K 线必爆上下文,只能用本地数据
- 用户装了通达信(默认路径
C:\new_tdx,可用ls -d /c/*/ | grep -iE "tdx|zd_|tong"找) - 盘后静态筛选、周末筛选、历史回算
先确认数据源存在:C:\new_tdx\vipdoc\sh\lday\ 应有上万个 .day 文件。若为空,说明用户没下载盘后数据,需提示他先做「盘后数据下载」。
为什么不能用 MCP
| 路径 | 结论 |
|---|---|
| westock tool_filter / data_kline | 批量 K 线返回体巨大,2891 只全拉直接爆上下文 |
| ifind search_securities 自然语言选股 | 扛不住复合逻辑。"MACD底背离 + 创新低 + 市值>50亿" 这类多条件查询返回空,提示降低筛选难度 |
| westock data_sector constituent 批量 | 服务端不稳定,会随机 service error |
→ 唯一可行路径:读本地二进制。 5259 只全量约 10 秒。
数据源同步:让 .day 每天自己更新(前置条件)
扫描 100% 依赖本地 .day,数据新鲜度就是一切。三条路实测结论(2026-09):
| 方案 | 结论 |
|---|---|
| 通达信自带定时下载(首选) | 官方、增量(每只加 1 根,约 170KB)、免费。开关在 C:\new_tdx\T0002\user.ini:TimeDown=1 开启,DownMin=960 = 16:00(分钟数),DownAllABGp=1 全 A/B 股。UI:系统设置 → 设置1 →「定时自动下载日线 16:00」 |
| 官方全量包兜底 | https://data.tdx.com.cn/vipdoc/hsjday.zip,524MB,每交易日约 15:58 更新。不依赖通达信运行,适合出差/关机后补齐、换机重建 |
| pytdx / mootdx / tdxpy | 已废,别再试。公开行情服务器 7709 已收紧:connect 和 get_security_count 能通,但 get_security_bars / get_security_quotes 一律返回空,mootdx 的 bestip() 也选不出可用节点 |
关键坑(都踩过)
- 改
user.ini必须先关闭通达信 —— 运行时改会被它退出时的内存配置覆盖回去。 - 官方包地址挂在 TencentEdgeOne 后面带 JS 反爬:
urllib/requests一律被拦(返回 987 字节EO_Bot_Ssid混淆脚本,还伪装成 HTTP 200),只有 curl 能过(TLS 指纹差异)。Windows 自带C:\Windows\System32\curl.exe,HEAD 也要用curl -sI。 - 定时下载要求 16:00 通达信在运行。要无人值守就用计划任务 15:55 拉起它(
scripts/tdx_autostart.ps1),ps1 必须存成 UTF-8 with BOM —— 否则 PowerShell 5.1 按 GBK 解码中文会报莫名其妙的语法错误(报的位置完全不对,极具误导性)。 - Windows 侧工具坑:
schtasks.exe常被沙箱程序黑名单拦截(不可重试、不得绕道),改用 PowerShell 的Register-ScheduledTask;且 PowerShell 工具的 stdout 不回显,验证结果要写文件再读。 - 覆盖 vipdoc 时只覆盖、不删除:官方包 12411 个品种(沪 5945/深 5857/京 609),本地通常 18536 个,差集多是债券回购(
sh01xxxx、sh018xxx)。A 股实测零缺失(可以放心兜底),但删掉那些债券文件会影响通达信自身。 - 下载实测 523.9MB 仅 10 秒,没必要长期留缓存;脚本把它放在系统临时目录,不进项目。
用法见 scripts/sync_tdx_official.py:无参=体检,--download 只下,--apply 覆盖,--apply --dry 演练,--force 忽略阻拦。内置防倒退校验(包内日期 < 本地就中止)。
二进制格式(踩坑记录,照抄不要重写)
1. 日线 vipdoc/{sh,sz,bj}/lday/*.day
- 文件名带市场前缀:
sh600519.day,取代码要剥掉前 2 位 - 32 字节/条定长:
date,open,high,low,close各 uint32(÷100 得价格)、amountfloat32、volumeuint32、reserved struct.unpack("<IIIII", rec[:20])
2. 交易日历
- ⚠️ 指数文件
sh000001.day更新滞后(实测慢 2 个交易日),用它当日历会把大量正常票误判为停牌 - ✅ 用一只全历史个股代替,如
sh600519.day
3. 股票档案 T0002/hq_cache/base.dbf(标准 dBaseIII)
- 字段:
SC(市场,单字符 0=深 / 1=沪 / 2=京,不是 "sh"/"sz")、GPDM、HY、LTAG(流通股本,单位万股)、SSDATE - 验证方法:平安银行 LTAG=1940568.50 万股 = 194 亿股 ✓
- 解析:读 32 字节头拿 nrec/hlen/rlen,再从 32 循环读字段描述符直到遇到
0x0d
4. 股票名称 T0002/hq_cache/{shm,szm}.tnf
- 定长 314 字节/条(相邻代码偏移恒为 314)—— 不是变长!
- 代码在记录头,名称在代码末尾 +23 字节处(即
+6+17),GBK,0x00结尾 - ⚠️ 致命坑:必须按 市场+代码复合索引。
shm.tnf的000039是「上证信息」指数,若只按 6 位代码建 dict,会覆盖深市000039(中航精装),导致名单里混进「上证周期」「科创芯片」这类指数名 - ⚠️ 用全局正则扫 6 位数字会命中记录内部的其他数值(数值字段),读到串位垃圾。必须确认 +23 偏移落在有效范围内
- 名称含全角空格(万 科A),需清洗
.replace("\u3000","").replace(" ","").replace("\uff21","A") - 上市次新标记:
N=上市首日,C=未满 5 日 → 用^[NC][汉字]过滤
5. 概念板块 T0002/hq_cache/block_gn.dat(自研 "Registry ver:1.0" 树形二进制)
此前误判为 Windows registry 不可解析,实际结构很简单:
名称(GBK) + 0x00 + uint16_le 成分数 + 0x00 0x02 0x00 + [6位ASCII代码 + 0x00] * n
- 解析出 303 个板块,declared 与 parsed 零误差(以此自检是否解析正确)
- 用 GBK 字节范围找中文名:
[\xb0-\xf7][\xa1-\xfe],ASCII 用[\x41-\x5a\x61-\x7a\x30-\x39] - ⚠️ 通达信成分上限 400 只,超出的大板块(国防军工 / 人工智能 / 消费电子 / 一带一路)成分被截断 → 渗透率虚高,报告必须标注
block_fg.dat是风格/财务标签(融资融券、业绩预增、破净资产),不是资金主线,做板块共鸣必须剔除,只用block_gn.dat(概念)
6. 板块指数名称 T0002/hq_cache/shs.tnf
- ⚠️ 与
shm.tnf/szm.tnf结构不同:这里是步长 360 字节、名称在代码末尾 +25(记录起点 +31)。 沿用 314/+23 会解析出 0 条;用 +30 也会差一个字节、结果全部为空 - 确定偏移的通用方法:扫描「代码之后第一个非 0x00 字节」的众数偏移,实测稳定为 31
- 覆盖 880/881/882 段 652 个板块,是画板块 K 线的唯一名称来源
- 板块指数日线直接读
vipdoc/sh/lday/sh880xxx.day,格式同普通日线 - ⚠️ 部分细分概念(三代半导、人形机器、可控核变…)在 shs.tnf 里没有对应指数,覆盖率约 87%, 界面上必须提示「通达信无对应板块指数」
7. incon.dat
T 码分类(T1001|银行),与 base.dbf 的 HY 数字码不是一套,别指望用它做行业映射。
工作流:缠论四类买点 + 板块共鸣
缠论结构本身(包含→分型→笔→中枢→背驰→四类买点的算法与画图)已抽成独立技能
chanlun-kline,那里有可直接复用的scripts/chanlun_core.py、scripts/kline_canvas.js、scripts/case_svg.py。 本节只讲它在全市场扫描流水线里怎么串。
核心纪律:四类信号必须彻底分表统计,不能混在一个池子里。 已用数据验证 —— 四类 P0 相差数十倍, 混算只能用单一 P0,渗透率倍数全部失真。Top10 Jaccard:一类vs二类=0.000、二类vs全部=0.000、 一类vs突破=0.176(唯一有意义的跨榜组合:同时具备"底部结构+突破"的交接板块)。
cd <工作目录>
python chanlun_scan.py # ① 全市场结构扫描 -> chanlun_hits.csv(约 10 秒)
python fund_flow.py # ② 全市场资金流 -> fund_flow.json(约 50 秒,可缓存复用)
python resonance4.py # ③ 四类分别统计 + 末端资金确认 -> 4 CSV + resonance_data.json
python export_kdata.py # ④ 导出 K 线 -> kdata.json
python build_dashboard.py # ⑤ 渲染单文件看板 -> chanlun_dashboard.html
python export_tdx_blocks.py # ⑥ 生成 .blk(先 --install 需关闭通达信)
资金必须在「末端」确认,绝不能前置过滤(本流水线最大的设计坑):
resonance4.py 的 FUND_MODE 默认 "post" —— 共鸣榜按结构统计(N / 渗透率 / 时间系数
不受资金影响),资金只作为「能不能下手」的确认标记。
- ❌
FUND_MODE="pre"(前置砍掉 d5≤0 的票再统计共鸣)会制造统计事故: 二类买点 13 只 × 全市场 d5>0 占比 32.7% ≈ 4 只,4 只票要凑够同板块 N≥3,概率接近 0 —— 结果就是二类买点整类消失。这不是市场没有二类,是被过滤顺序抹掉的。 对大样本类别(中枢突破 246 只)无害,所以这个 bug 极具隐蔽性,只会杀死小样本类别。 - ✅
post:结构榜完整保留,每只票带fund_ok,每个板块带n_fund(命中股中资金为正的数量) 与confirmed(n_fund >= CONFIRM_MIN_FUND,默认 2)。可交易层在export_tdx_blocks.py的 CLPICK 补齐:板块 fnet>0 + 广度≥40% + confirmed + 个股 fund_ok。
资金面要点:
- 数据源必须走东方财富资金流接口:通达信本地
vipdoc下没有 zjlx 目录,拿不到资金流 - 字段:
f62今日主力净额、f1645日主力净额、f1655日净占比(f165是百分比不是金额,别混) - 板块级资金用全成分口径(不是命中股口径——命中股已被过滤必为正,没有信息量):
fnet= 板块全部有效样本 5 日净额合计(可为负)、fbread= 净流入为正的成分占比 - 共鸣分高但板块资金为负 = 结构到位、资金不认,必须降级——这是本流水线最核心的判定
看板(推荐交付形态):四类各自成卡片、点击板块名弹出板块指数 K 线(并列出该板块命中个股)、 点击个股名弹出个股日线,自动叠加 MA5/10/20、中枢 ZG/ZD 区间、止损位、买点位置竖线。 全部数据内嵌、零 CDN,双击即可离线打开。
弹窗导航(必须实现,否则用户会迷路)——三级可回溯:
- ⚠️ 派生名单必须一起导 K 线:二类候选池这类名单不在
resonance_data.json的 sectors 里,export_kdata.py要单独把它们读进来pack(),否则看板上"能看见点不动"—— 用户点个股名只会弹alert('该标的不在本次K线数据范围内')。 - ⚠️ 同一只票可能命中多种信号(既是「一类买点」又是「二类候选」),
STK必须按信号类型分桶存notes/stops/zgs/dates,弹窗用pick(field, 当前ty)取值。 只存一份的话,点「二类候选」会看到一类的话术("底背驰"),语义直接错乱。 - ⚠️ 候选/命中要两张表(
SECSTK/WSECSTK):面包屑"该股同属"要合并两家, 但板块弹窗的"命中个股"不能混入候选(候选不是买点)。 - ⚠️
details折叠块 +[data-sec]会與榜单选择器冲突:冒烟测试里pg.click('[data-sec="XX"]')因 strict mode 命中多个而失败,要写成.card table:not(.mini) [data-sec=...]。 - 面包屑
← 返回 <板块名> › <个股名>,点击返回;Backspace等效(Esc 仍是直接关闭) - 个股弹窗内保留同板块其他命中个股 chips,当前项
.on高亮,可在个股间横向切换 - 个股若同属多个板块,面包屑里额外列出(最多 3 个),点哪个跳哪个
- 实现要点:
STK2SEC由SECSTK反查(同一股在同一板块可能命中多种信号,必须按 code 去重); 导航栈NAV=[{f:openSec,a:[sec]}],个股层的上级永远是板块层
术语区:页面底部折叠的「术语速查」(ZG/ZD/中枢/渗透率/共鸣分), 个股弹窗 kv 行也直接列出 ZG/ZD 数值并带 title 提示——用户第一次看必然问这两个缩写是什么意思。
必做冒烟(K 线渲染坑多,务必验证 Canvas 真的画出内容):
# 用系统 Python(已装 playwright + 浏览器),managed python 没有
python smoke_test.py chanlun_dashboard.html
它检查:卡片数、板块弹窗、个股弹窗、三类买点中枢带、Esc 关闭、控制台报错,
以及导航链路(面包屑点击返回 / Backspace 返回 / 同板块个股横向切换)。
用 getImageData 采样判断画布非空——只看 DOM 存在不算通过。
共鸣强度公式
Score = N × (P / P0) × T_adj
N 板块内命中数,主榜门槛 N ≥ 3(**含 3**,代码是 `if N < MIN_HITS: continue`,不是 >3)
P 渗透率 = 命中数 / 板块有效样本数
P0 该类信号的全市场基准命中率(四类各自独立!)
T_adj ≤10日 1.0 / 11~15日 0.6 / 16~25日 0.3 / 26~30日 0.15 / >30日 0
主榜 / 观察区必须分区:WATCH_HITS = 2 —— N==2 的板块进观察区并打 watch 标记,
排在正式榜之后,不进 Jaccard 重叠矩阵、不进通达信自选股。
不分区的话,小样本类别(二类只有个位数)会被 N=2 的凑数项"救活",看板看起来有内容,
实际是拿不到共鸣门槛的线索 —— 这会掩盖"该类信号当前确实没有板块效应"这个真实结论。
信号定义要点(易错)
- 一类买点:下跌 MACD 面积背驰 + 创新低 + 缩量。左侧,仓位最小
- 二类买点:必须是「确认 → 回踩 → 不破」完整结构 —— 先有 ≥3% 反弹,再回踩不破一类低点。
⚠️ 只要求"没创新低"是不完整的,会把横盘误判为二类
⚠️ 信号日期必须取回踩低点当日,不能用最后一根 K 线 —— 否则所有二类 span=0、时间系数全满分
🔴 最容易漏的时序校验(v5 修复):算出
peak_rel(反弹高点相对一类低点的偏移)后, 必须与回踩低点位置j比较,写成j > i_b1 + peak_rel。 只写peak_rel > 0(即定义了却没参与比较)= 要件形同虚设:一类低点刚过、还在磨底的低点 会被当成"回踩低点",那不是回踩是没起来。实测这个漏判会把伪二类从 6 只放大到 33 只(+450%)。 - 二类天然稀少,别急着调参:二类依赖"一类后先反弹再回踩"这个两段式结构,与一类在时间上错开。
典型漏斗(2026-09-12 全市场 5259 只):一类 392 → 过反弹门槛 365 → 过回踩时序 73 → 不破前低 6。
中间 292 只(75%)是"一类后一路上行、还没回踩",它们才是二类的预备弹药库 ——
chanlun_scan.py已单独输出为chanlun_2buy_watch.csv(不进四类分表,导出通达信CL2W)。 所以"二类为 0"往往说明回踩还没发生(一类刚集中爆发),而不是参数太严。 ⚠️ 候选池必须排除现价已跌回一类低点下方的票(close > low1)—— 那是一类买点失败, 不是"待回踩"。实测 91 只里有 21 只(23%)属于这类,混进来会严重污染候选池质量。 - 候选池的板块分布 = 二类买点的前瞻指标:候选越集中、资金越正的板块, 回踩一旦发生就会率先批量转化为二类。这是"二类当前为 0"时唯一有预测价值的输出, 比盯着空的二类榜有用得多。
- 中枢突破:与前两类互斥在后;属突破交易,需板块共振
- 三类买点:突破后回抽不落回中枢,四个要件缺一不可(v4 起收紧): ① 回抽低点 > ZG ② 真实回撤 ≥5%(排除"刚突破还没回调") ③ 回踩低点须在突破高点之后(时序) ④ 现价距 ZG ≤30%(涨太远则止损太远,风险收益比不成立) ⚠️ 信号日期取回抽低点当日,不是突破日
已知局限(每次交付必须声明)
- 结构筛选器固有偏好:突破 / 三类天然偏向低波动、长期横盘的票(银行 / 高速 / 公用), 会"像主线"但实际只是适合被这种几何捕捉到。渗透率归一化只能削弱,无法消除 (实测:叠加资金硬过滤后,这类板块在四张榜 Top20 里全部消失 —— 双过滤确实修掉了这个偏差)
- 资金流是单日快照:5 日窗口偏短,单日巨量异动会被放大;要更稳可叠 10 日
- 板块资金为负 ≠ 一定下跌:它代表主力在减仓,是降级依据,不是做空依据
- 千人千缠 + 重绘:笔/线段划分带主观性,中枢会随新数据回溯改写。实盘信号不稳定
- 报告输出需匹配 IDE 主题,light 主题禁止用深色背景
scripts/
| 文件 | 用途 |
|---|---|
| tdx_reader.py | 本地数据读取模块(日线 / 档案 / 名称 / 概念板块 / 板块指数),含全部踩坑注释,直接复用 |
| chanlun_scan.py | 缠论结构扫描 → chanlun_hits.csv(含三类买点四要件收紧) |
| fund_flow.py | 全市场主力资金流抓取(东财批量接口)→ fund_flow.json |
| resonance4.py | 四类分别统计的共鸣引擎(末端资金确认,主榜 N≥3 / 观察区 N=2 分区) |
| export_kdata.py | 导出板块 + 个股 K 线(列式紧凑存储)→ kdata.json |
| export_tdx_blocks.py | 导出通达信自定义板块(.blk + blocknew.cfg),含三态运行检测 |
| build_dashboard.py | 主交付:单文件看板(四类卡片 + Canvas K 线弹窗) |
| build_report.py | 旧版 tab 式 HTML 报告(保留对照) |
| smoke_test.py | 看板浏览器冒烟(需额外装 playwright),用法 python smoke_test.py [看板HTML] [截图目录],两者默认取 TDX_SCAN_OUT 或当前目录 |
| sync_tdx_official.py | 官方全量日线包兜底同步(必须用 curl 下载,防倒退 + 只覆盖不删除) |
| tdx_autostart.ps1 | 配合计划任务 15:55 拉起通达信(需 UTF-8 with BOM),好让 16:00 定时下载触发 |
所有脚本与环境/个人路径无关,两个输入输出变量都走环境变量:
| 变量 | 作用 | 默认 |
|---|---|---|
| TDX_HOME | 通达信安装目录(数据源) | C:\new_tdx |
| TDX_SCAN_OUT | 输出目录(中间文件与看板都落这里) | 当前工作目录 |
流水线各脚本必须共用同一个输出目录——它们通过 resonance_data.json、
chanlun_hits.csv 等中间文件串联。想换目录就把两个脚本放在同一目录下运行,
或统一设 set TDX_SCAN_OUT=D:\scan 后再依次执行。
必须按 chanlun_scan → fund_flow → resonance4 → export_kdata → build_dashboard 顺序执行。
回流到通达信(可选收尾,用户是通达信用户时强烈建议做)
把四类命中直接写成通达信自定义板块,看盘时一键调用。格式已从本地现有文件逆向确认:
.blk成分文件:纯文本 GBK,每行 7 字符 = 市场前缀(1=沪 0=深)+ 6 位代码,行尾 CRLF (例1601566\r\n0000852\r\n)T0002/blocknew/blocknew.cfg:定长 120 字节/条[0:50]名称 GBK 补 0x00[50:120]板块代码 ASCII(= .blk 文件名) 校验方法:文件长度必须能被 120 整除(现有 1560 = 13 条,与 NZ/DNQD/WPXG 完全对应)- 追加新板块 = 备份 cfg → 末尾 append 120 字节记录 → 回读验证「原始记录逐字节未变」
⚠️ 两个必须记住的坑:
- 通达信运行时不能写 cfg(退出时会用内存配置覆盖)。但不要用 try/except -> return False 做进程检测:
沙箱/受限 shell 里
tasklist可能「返回码 0 但看不到宿主进程」,于是乐观判定"未运行"而误写。 必须做三态检测:running/not_running(命令跑通且输出里有其他进程)/unknown, 且 unknown 时一律不写,要求显式--force。判断"未运行"的充分条件应包括 「输出行数 > 5」这类旁证,不能只看 returncode。 - 只在 cfg 真的要变更时才备份,否则反复执行会堆一堆备份文件。
python export_tdx_blocks.py # 只生成到 ./tdx_blocks/(安全)
python export_tdx_blocks.py --install --force # 关闭通达信后写入(--force 表示已知悉)
python export_tdx_blocks.py --uninstall --force # 一键移除(cfg 记录 + .blk 文件)
外部接口踩坑(东财资金流)
- ⚠️
push2.eastmoney.com连续批量请求几十次后会RemoteDisconnected封禁,而且是全节点一起封 (82./1./48. 等所有 push2 前缀都一起失效)。必须用push2delay.eastmoney.com(延时节点), 资金流是收盘统计值,延时节点完全够用 - 批量用
api/qt/ulist.np/get,secids形如1.600519,0.000001(1=沪 0=深), 单批 50 只、间隔 0.25s、pz必须等于 secids 个数,否则返回不全 - 请求头带
Referer: https://quote.eastmoney.com/更稳 - 失败重试时轮换节点,不要死磕同一个
历史归档(按季度分级)+ 看板日历回看
主产物 chanlun_dashboard.html 是固定文件名、每次覆盖。不归档的话上周榜单就永久
丢失,无法回答「当时的主线是什么」。build_dashboard.py 已内置归档 + 回看。
两级存储
| 文件 | 内容 | 体积 |
|---|---|---|
| history/lite_{YYYYMMDD}.json | 本期榜单(full:Top10 板块 + 每板块前 8 只个股) | 约 40 KB |
| history/lite_{YYYYMMDD}.json | 跨季度后降级 mini:仅 Top8 板块名 + 核心指标 | 约 5 KB |
| history/dashboard_{YYYYMMDD}.html | 完整看板快照(仅本季度保留) | 约 3 MB |
| history/snap_{YYYYMMDD}.json | 周报用(候选池 + Top10 板块名,由 weekly_report.py 写) | 约 8 KB |
save_and_prune() 每次运行做三件事:
- 写本期 lite(full)
- 把非本季度的 lite 降级为 mini(删掉 stocks 字段)—— 实测 40KB → 5.4KB
- 删除非本季度的
dashboard_*.html
看板日历
顶部「历史回看」区块:按月展示、有快照的日期高亮可点(本季度蓝色、跨季度灰蓝、
当期带橙色内框)、‹ › 切月、回到最新 复位。
点击历史日期会同时替换 #hero(四类概览卡)和 #cards(四张榜单)——
两处必须联动,否则会出现「顶部是最新、下方是历史」的自相矛盾。
踩坑
- ⚠️
kdata.json的dates是整数(20260911)不是字符串,直接len()/切片会抛object of type 'int' has no len()。统一走ymd()转字符串 - ⚠️ 用数据日期命名快照,不用当天日期。通达信没下载盘后数据时,今天跑出来的 仍是上一交易日结果,用今天命名会造成「以为跨越了一周」的假象
- ⚠️
main()里d已经是resonance_data,归档时不要复用变量名d main()里变量CURDATE/HIST/HISTLV/HISTSTAT由 Python 注入为全局, 冒烟脚本可直接window.CURDATE取值- 日历走了独立的 IIFE + 第二个
<script>块,靠document上的事件委托工作, 因此替换innerHTML后无需重新绑定(原 JS 也是委托在 document 上的,别改成直接绑定)
冒烟必须覆盖
日历切换要验证「概览 + 榜单一起变」:记录切换前 #hero .stat .v,点历史日期后
对比是否变化,再点 回到最新 验证能否复位。只检查日期格子存在是不够的。
Scan to join WeChat group