股票面板这轮更新:数据全量入 PG,和一个 markdown 表格的坑
自己的股票战术面板(FastAPI + Jinja2 SSR 的只读看板,配中短线策略用)最近攒了几笔更新,顺手记一下。更新本身都不算大,但最后那个 bug 的排查过程还挺有代表性。
数据层:md 彻底退役,全量切 PostgreSQL
面板最早的数据源是一堆 markdown 文件——持仓、选股池、参数,谁改了文件,面板就显示谁。单人用的时候这套能跑,但”文件即状态”的问题越攒越多:手工编辑会被下一个定时任务悄悄覆盖、并发写没有章法、想查历史只能翻文件备份。
这轮直接激进了一把:所有状态进 PostgreSQL,md 降级成纯导出视图(想要文件可以从库里导出,但面板只认库)。写入方统一走 upsert 脚本,面板用只读账号连库,读写彻底分开。
改完最直观的感受:数据链路从”猜文件是谁写的”变成”查表”,排查问题快了不止一点。
池页与细节:日更数据源 + 三态标签
选股池页动了两处:
- 数据源换成每日落库的评分表(08:30 / 15:05 定时写入),不再依赖每周快照,开盘日当天就能看到新数据
- 状态标签做成三态互斥:绿色(达标)、黄色(临界)、拦截(规则排除)——之前”未达门槛”和”拦截”混在一起,语义不清
外加全站表格内容居中(长文本列保持左对齐)、标签行距统一这些琐碎但影响观感的调整。
今天的坑:表格渲染成了一堆竖线
下午收盘报告的详情页突然不对劲——markdown 表格没变成表格,显示成一行行带 | 的裸文本。
排查先做对照:同一条渲染管线,盘前报告正常、收盘报告不正常,那差异必然在输入,不在渲染器。两份 markdown 摆一起,结构差异一目了然:
1 | |
盘前是标准标题加空行再接表格;收盘那次 LLM 输出用了粗体行代替标题,还紧贴表格没有空行。python-markdown 的块解析会把”文字行 + 表格行”整体当成一个段落,tables 扩展一看首行不是表头就放弃转换——整块按段落输出,表格就此退化成原文。
修复只加了一行正则,渲染前把「文字行 → 表格行」的边界补上空行:
1 | |
选择修渲染器而不是改 prompt,理由很直接:渲染器修一次,覆盖全部历史报告和未来所有输出变体;改 prompt 只约束以后的输出,还拦不住模型偶尔的自由发挥。修完本地复现页 tables=3、裸管道=0,推 GitHub Actions 构建镜像,TrueNAS 拉取重启,线上复验通过。
写在最后
这轮更新没有炫酷的新功能,全是”让已有东西更可靠”的活——数据收敛到唯一状态源、语义补齐、渲染容错。个人项目做到后期,大部分时间其实都花在这类事情上。