如何开发一个在线更新的 A 股筛选器?网上的教程大多教到「装个行情库、写个循环、把选出来的票打印出来」就收工了。可真要它每天收盘后自己更新、挂在网上给别人看、一用好几年,问题马上就变了:数据源当天没入全怎么办?需求方没说清的口径谁来定?改了一行代码,线上跑的是哪一版?半夜断网,补到一半的历史还算不算数?
这篇就从这几个问题出发。答案有一半在代码里,另一半在代码之外。
本文速览 · 摘要 · 定义 · FAQ
TL;DR
- 一位资深 A 股投资者朋友给了一张「三档市值 × 两种信号 × 六个条件」的阈值表。三周后,它长成了覆盖全部 A 股、2015 年以来十年日 K、八个模块、每个交易日一条命令自动更新的盘后监控系统。
- 前六天野蛮生长:没有一份需求单,线上当验收场,一天部署 9 次只提交 2 次。复盘之后立了两样东西:六阶段 + 三档位的工作规矩,和写进程序里的两道闸门(未提交不部署、数据骤降即拦截)。
- 立规矩之后五轮,约 85 小时,217 个提交,14 次上线,自动化测试从 341 项涨到 1,090 项,线上每一版都对得上一次提交。
- 可迁移的方法论是四根柱子加一副地基:流程(先写后做)、闸门(规矩写进程序)、证据(对拍胜过自信)、分工(人定方向、按按钮,agent 干活),地基是架构克制(唯一写入口、模块只读、零依赖、静态页)。
Definition
规矩先行的 AI 协作开发(rules-first AI-assisted development),指在大模型 agent 承担主要编码工作的项目里,先把「需求怎么记、在哪验收、什么时候能上线、出错时怎么停」写成成文规矩,并尽量把其中的硬约束做成程序闸门,而不是寄希望于人或模型每次都自觉遵守。它和「让 AI 写得更快」是两个问题:前者管的是每一次上线是否说得清是哪一版、为什么、凭什么,后者只管速度。
FAQ
有 AI 写代码了,为什么还要需求单、验收、标签这些「老一套」?
因为 AI 把写代码的成本压得极低,返工的成本却没降。写得越快,没想清楚就开工、在线上试错、版本对不上提交的毛病就暴露得越快。规矩管的是方向和边界,恰恰是 agent 自己管不住的那部分。
「闸门写进程序」和「写在文档里要求遵守」差在哪?
文档里的规矩靠记性,程序里的闸门靠机制。本项目的部署命令开头先查 git:程序、配置、说明书有未提交改动就拒绝发布,而且有意不留绕过开关。人会忘,模型会在长对话里漂移,程序不会。
这套系统能用来炒股赚钱吗?
不能这样理解。它只做筛选和记录,不做收益回测,不给买卖建议。本文讲的是系统怎么开发,不是信号好不好。
这套方法离开 A 股还用得上吗?
用得上。凡是「需求方说不清口径、数据每天在变、结果要长期留档」的系统,比如运营报表、监控面板、内部数据工具,都是同一类问题。
References and Further Reading
- Betsy Beyer 等,Site Reliability Engineering,O'Reilly,2016,第 8 章 Release Engineering(发布工程:可追溯、可复现的上线)。
- Michael Feathers,Working Effectively with Legacy Code,2004(特征测试:改动前先把现有行为钉成基准)。
- Kent Beck,Test-Driven Development: By Example,2002(测试先行)。
- TradingView,Lightweight Charts(开源金融图表库,Apache-2.0),本项目个股 K 线图所用。
01 · 开门见山:系统不是写出来的,是管出来的
先说结论:一个靠 AI 写代码的项目,真正的瓶颈从来不是代码,而是管理代码进入现实世界的那道门。
故事很朴素。一位做了多年 A 股的朋友,手里有一套看盘的老经验,凝成一张表:小、中、大三档市值,温和与强两种启动信号,换手率、量比、振幅、收盘形态、突破位置等六个条件,每个条件一档一档的阈值。他的诉求也简单:每天收盘后,帮我把符合条件的票挑出来,别让我一只只翻。
三周后,这张表长成了这样一套东西:
| 维度 | 起点(10-07) | 现在(10-21 第五轮后) |
|---|---|---|
| 覆盖范围 | 一个固定股票池,约 100 只 | 全部 A 股,外加 269 个指数与板块、宽基 ETF |
| 历史深度 | 两年 | 2015-01-05 起,2,864 个交易日,日 K 1,184 万行 |
| 模块 | 启动信号一个 | 启动信号、筹码线、指数与板块、情绪、宽度、榜单、资金、个股 K 线图 |
| 程序 | 5,457 行 | 12,523 行,只用 Python 标准库,零第三方依赖 |
| 自动化测试 | 341 项 | 1,090 项,全部通过 |
| 每日运维 | — | 一条命令,约 5 分钟,自动发布成静态网站 |
写代码的主力是 AI:一个主会话负责规划、调度、验收和归档,若干子 agent 分头写各模块和测试,另请一家不同来源的模型只读审查。人只做四件事:转达需求方原话、定口径、验收点头、亲手按部署键。
这篇不讲 A 股,讲的是这三周里摔过的跟头,和跟头摔出来的规矩。不以规矩,不能成方圆,老祖宗两千多年前就说透了。只不过这一回,规矩不是写给人看的,是写给人和 AI 一起遵守的,最硬的那几条,干脆写进了程序。
02 · 野蛮生长的六天:勤快救不了流程
10 月 7 日到 12 日,项目跑得飞快。启动信号、历史回看、估值与公告建档、全市场筹码线扫描、在线网站、每日一条龙、指数与板块状态表,一周之内接连上线。24 个提交,每一个都带测试。
看上去很勤快。说实在的,问题就出在这份勤快上。
12 日晚上做了一次复盘,拿后来定下的六个阶段逐项对照这 24 个提交,结论扎心:
| 毛病 | 证据 | 后果 |
|---|---|---|
| 没有一份写在开发之前的需求单 | 11 个作品,0 份 | 当初为什么这样定,要翻对话、注释、文档好几处才拼得出来 |
| 线上被当成验收环境 | 10-11 上线后一小时连补 3 个 fix;板块页的宽度是在线上量的,为此多部署 4 次 | 需求方随时可能看到半成品 |
| 线上版本对不上提交 | 10-12 部署 9 次,提交只有 2 次,全程没有标签 | 说不出「现在线上是哪一版」,出了事也退不回去 |
| 一个提交装好几件事 | 筹码线、网站、每日一条龙三件事一个提交,20 个文件 2,459 行 | 出问题没法只退其中一件 |
| 文档跟在代码后面补 | 4 个单独的「对齐文档」提交 | 补文档时才发现代码里的坑 |

这像一支技术不差、跑动积极的球队,没有阵型,也没有换人纪律。每个人都在拼,可球一丢,谁也说不清是谁的位置空了。勤快是美德,但勤快填不了流程的窟窿,只会让窟窿漏得更快。AI 写代码尤其如此:模型不累、不烦、出活极快,人一兴奋,就忍不住「先上去看看效果」。千里之堤,溃于蚁穴,线上的每一次「先看看」,都是一个蚁穴。
03 · 立规矩:六个阶段,各守各的边界
复盘当晚,规矩写进了项目入口文档。核心是一张六阶段表,每一步都写明做什么、边界在哪、交出什么:
| 阶段 | 做什么 | 边界 | 产出 |
|---|---|---|---|
| 1 需求单 | 需求方原话、我们的理解、上线形式、不做什么、待定项、验收标准 | 只写文档,不动程序和配置 | 一份带日期的需求单,写完即提交 |
| 2 探索(可选) | 数据拿不拿得到,算出来有没有用 | 只读主库,脚本和数据另放,不发布;允许结论是「不做」 | 研究日志 |
| 3 开发 | 先写测试再实现 | 在分支上做,不部署;主干必须每天 17 点能正常跑 | 代码与测试 |
| 4 验收 | 本地生成站点,电脑和手机宽度各截图 | 不碰线上,版式在这一步量好 | 负责人点头 |
| 5 上线 | 合入主干 → 部署 → 打标签 | 有未提交的改动,程序拒绝部署 | 标签 |
| 6 归档 | 更新说明书、入口文档,在需求单末尾记下实际做成了什么 | 说明书不早于功能 | 文档提交 |
但不是每个小改动都要走全套六步,否则规矩就成了枷锁。所以再按大小分三档,拿不准就往大的一档靠:

这张表里有几条看着不起眼,后来都证明是关键:
说明书不写在前面。 系统的使用说明就是网站上的一页,每天随数据一起发布。先把新功能写进说明书,需求方当晚就会读到一个还不存在的功能。先写的应该是需求单,说明书只能在验收通过、合入主干之后改,和功能同一次上线。
上线形式在需求单里定。 这个站是纯静态页,只有五类地方允许带脚本:阅读读数、表格排序、说明书点图放大、首页按日期定位、个股 K 线图。别处想加脚本、动画,就算改规矩,按「大」档处理,先出本地原型给负责人看。克制是一种设计:页面越朴素,出错的面越小。
点头即授权。 负责人在第 4 步点头,就是第 5 步合入和部署的授权,不用再问第二遍。规矩要防的是失控,不是要人反复说 yes。
要求变了,回到第 1 步。 需求方的想法会反复,会越挖越深,这再正常不过。可一旦在开发途中边做边改口径,需求单就成了废纸。改需求单只要几分钟,却能让后来的每一步都知道自己在对什么标准干活。
04 · 规矩要长出牙齿:把闸门写进程序
写在文档里的规矩,靠的是自觉。人会忘,模型在长对话里也会漂移,熬到凌晨两点,谁都有「就这一次」的时候。所以最硬的几条,直接写进了程序。
闸门一:未提交不部署。 部署命令开头先查 git:程序、配置、说明书这三处只要有未提交的改动(包括已暂存的、新增未跟踪的),就拦住,日志列出是哪几个文件,网站不更新。为什么只查这三处?因为它们决定线上长什么样;写一行开发笔记、改一个测试,不该让当天的网站停更。最要紧的一条是:有意不做绕过开关。留了后门的闸门,迟早会被走成大门。
闸门二:数据骤降即拦截。 每天会变的只有上游数据,所以发布前只设一道数据自检:今天全市场的股票只数,比前一个交易日少了超过 5%,就拦住发布,弹一条通知,等人核对。防的是数据源当天还没入全、只返回一部分股票,程序却把这天记成「已同步」,名单从此永久少一截,而且没有任何提示。这个阈值不是拍脑袋:500 个交易日里单日最大降幅只有 0.48%,日常波动碰不到 5%;而 2015 年 7 月千股停牌那几天会被拦下,核对后人工放行,属于预期之内。
两道闸门之外,还有一条贯穿每日流程的铁律:任何一步没做成就停下,宁可今天不更新,也不发布半截结果。

这里有个分寸:情绪、宽度、榜单、资金这些附加页面,出错只告警,不拦主流程。不能因为一页图表坏了,就让主名单也发不出去。该硬的地方要硬,该软的地方要软,这跟铁路信号一个道理:主干道的红灯必须停,侧线上的故障,挂个牌子绕过去就行。
立规矩的那一晚,规矩本身也按新规矩上线了一次。先写测试,再写闸门;验收时故意在工作区留了 3 个未提交的文件,直接跑部署,结果被拦住,日志列出 3 个文件,退出码 1,网站未更新。闸门第一次咬人,咬的是立规矩的人自己。这一口咬得好。
05 · 一口井,多根管:架构上的克制
10 月 18 日那一轮最大的手术,是把全市场行情抽成一个公共行情层。
在此之前,筹码线、指数板块、情绪各自去数据源取一份行情,各存各的。三张指数表里,同一个指数同一天的收盘可能来自三次不同的请求。这就像一个村子每户自己打井:水质对不对得上,全看运气。
手术之后,整个系统变成了星形:

| 原则 | 做法 | 好处 |
|---|---|---|
| 唯一写入口 | 只有公共层的两个文件能联网写行情表 | 数据只有一个来源,各页面不会各说各话 |
| 模块只读、互不认识 | 筹码线、宽度、榜单、资金……都只读公共层,各出各的报表 | 加一个新模块就是加一根只读的管子,不碰井,也不碰别人的管子 |
| 边界用测试守 | 模块边界测试自动检查:谁越界写了不该写的表,测试就红 | 架构约束不靠代码评审时的眼力 |
| 零第三方依赖 | 只用 Python 标准库;单文件 SQLite;静态 HTML + 内联 SVG | 没有包要升级,没有供应链风险,装好 Python 就能跑 |
最后一行值得多说一句。今天随手 pip install 一个库,几乎没有成本;可一个每天都要跑、要跑很多年的系统,每一个依赖都是一笔利息不明的长期贷款。唯一的例外是个股 K 线图用的图表库:它随站发布、不引外部地址,入库时核对 npm 包的 sha512,站点每次组装时再核对一遍 sha256,不符即中止。依赖不是不能有,而是要有就得认得清、锁得住。
公共层建好后,历史也一口气补到了 2015 年:约八千次接口调用,连续跑了一夜。中途网络断开两次,订阅额度撞到五小时上限停过一次,终端崩溃过一次。每一次都从日志里判断进度,从断点续上,没有丢一行数据。长任务必须可续传、自动重试、写日志,这条经验是那一夜一刀一刀刻出来的。
06 · 证据压倒自信:五道对拍
AI 写代码最大的陷阱,不是写错,而是写得像对的。测试全绿、页面好看、数字合理,偏偏某个角落差了一点,而这一点肉眼看不出来。
所以这个项目的验证,核心不是「测试通过」,而是对拍:拿一份独立的答案,逐位比对。

几个故事,比数字更能说明问题。
基准逐字节比。 重构公共层之前,先用旧代码把筹码线的全部产物出一份,存作「对照答案」。重构、补历史之后逐字节比:505 天里 501 天一字不差。差的 4 天,每天各多出 1 只股票,查下去全是同一个原因:旧起点下,停牌股的 K 线只有 93 到 100 根,不够公式要的 101 根;起点拉到 2015 年,够数了。差异不可怕,可怕的是说不清差异从哪来。
拿需求方的截图对拍。 均线通道那一轮,需求方深夜只发来一段通达信公式和 7 张截图,没有一个字的说明。没有去猜他要什么,而是先用库里的数据把 7 只股票的三条线复算一遍,读数逐一对上;再把截图上红箭头的位置,和计算出的「最低价回踩下轨」的事件段逐只对照,也对上了。意图从猜测变成了证据。更关键的一步在后面:如果只看当天碰没碰下轨,恰好会漏掉他举的三个例子,因为它们前一天碰轨、当天已经大阳离开。「回看 5 日」这个口径,就是这样从需求方自己的例子里推出来的。
同源逐位比。 个股 K 线图上画的三条线,和均线通道名单表上的数,用的是同一个算法。照理说不该有差,可测试用的是「近似相等」,偏偏放过了 .xxx5 这种舍入边界。改成 1,423 只股票的字符串逐一比,才抓出 5 只差了 0.001。根子在浮点:一边用前缀和,一边直接求和,最后一位四舍五入的方向不同。改用精确求和之后,已上线的名单逐字节不变,新图与表 0 差异。
换一家模型来挑刺。 审查不让写代码的同一家模型自己审,而是请一家不同来源的模型,只读审查,放在验收之前。几轮下来累计提出 40 余条问题,每一条都在真实库上复现属实,没有一条误报。其中最有分量的一条,是第一轮就抓到的:宽度模块的缓存,会把重拉或换了成份之后的旧读数发布出去。这类问题页面上看不出来,验收时根本发现不了。还有一条更直接:均线通道页上写的「停牌 32 只」,当天就是错的,应该是 3 只。
审查方也会掉链子。K 线图那一轮,第一家审查模型读完代码,撞上用量上限,没交清单。于是同一份委托书改派另一家,以只读模式审完,事后再查工作树,确认它没有改动一个文件。审查方要有备份,这条也是撞出来的。
测试管得住你想到的,对拍管得住你没想到的。两者缺一不可。
07 · 不替人拍板,也不反复追问:口径台账
需求方给的是一张经验表,经验表天然有空白。「大阳线配温和档的量能,算什么?」「市值分档用总市值还是流通市值?」「宽度的分母含不含停牌股?」这些问题,需求方没说,程序又不能不跑。
两种常见的处理都不对:替需求方拍板,等于把自己的理解偷偷塞进他的系统;每遇到一个就去追问,人家只是想看个名单,不是来陪你开需求会的。
这个项目的做法是第三条路:每个说不清的口径,都做成配置项、给一个默认值,记进台账。
| 台账字段 | 例子 |
|---|---|
| 编号与模块 | K7 · 高股息 |
| 坑是什么 | 股息率用近 12 月还是静态的排 |
| 现在的默认 | 近 12 月 |
| 谁定的 | 需求方 |
| 改了要重跑什么 | 只改配置,重出高股息页 |
10 月 18 日那一轮,台账记了 34 项:需求方定 13 项,负责人定 13 项,其余自查。当天下午需求方一口气回复了 12 条口径,两小时内全部落地,几乎只改了配置。启动信号那个最大的悬案,大阳线配温和量能算什么,至今没定,程序就老老实实标成「待定」,单列出来供人判断,绝不擅自归档。
台账的价值不在于记得全,而在于谁定的、默认是什么、改了重跑什么,一眼就能看清。它把「需求没说清」从一种焦虑,变成了一张可以慢慢清的账。
08 · 人机分工:agent 干活,人按按钮
这套方法里,人和 AI 的分工是这样的:

其中最有意思的一条是部署由人亲手执行。合入主干、生成站点、核对产物,这些 agent 都做好了,最后那条部署命令,交给负责人在终端里自己敲。这不是对 AI 的不信任,而是让「上线」这个不可逆的动作,始终有一个人类的手指按在上面。半自动,不是因为做不到全自动,而是有意留三分摩擦。
这一套跑下来,账是这样算的:
| 项 | 数字(五轮累计) |
|---|---|
| 模型分工 | 主会话 Claude Opus 5.5 · 子 agent Claude Sonnet 5.5 · 只读审查 Codex 与 grok |
| 时长 | 约 85 小时(10-17 23:14 → 10-21 11:55) |
| 提交与上线 | 217 个提交,14 次上线,每次打标签 |
| 模型调用 | 主会话与子 agent 共 2,325 次 |
| token 总量 | 约 6.21 亿,九成以上是缓存读取 |
| 按 API 标价折算 | 约 187 到 209 美元 |
| 实际付费 | 订阅制,不按 token 另计 |
其中两点值得单独说。
缓存才是大头。 九成以上的 token 是缓存读取,如果不用缓存、全部按基础输入价计,同样的工作量大约要贵十倍。长项目里,让上下文稳定、可缓存,本身就是省钱的工程。
效率提升几成,不知道。 开发过程中做过一次换算:同样的 token 量,按半年前的模型单价算,Claude 这一侧约贵一倍。但这只是单价差,不是效率差。旧模型可能要多走几轮、多返工,开发工具本身也在变,规矩本身又省掉了大量返工,混在一起拆不开。要可信的数,只能拿同一份需求单让新旧模型各做一遍。没做之前,任何「提升几倍」的说法都是猜。
09 · 摔过的跟头,都要记下来
方法论不是一路顺风写出来的。这三周里摔过的跟头,每一个都换来了一条规矩或一个习惯:
| 跟头 | 换来的规矩 |
|---|---|
| 夜里补历史,网络断两次 | 长任务可续传、自动重试、写日志 |
| 订阅额度撞到五小时上限,agent 中途被截断 | 提交勤落盘,断了也能从最近一个提交接上 |
| 终端崩溃,主会话断开 | 进度写在日志和看板里,新会话读日志续跑 |
| 开发看板的全表计数锁住了正在写入的库,补历史失败 | 写库时别并行读库 |
| 一天里有 11 个提交误带了不该有的署名行 | 提交前看一眼作者和署名;合并提交尤其要看 |
| 审查第一次开成了可写权限 | 审查一律只读,结论必须完整写在对话里 |
| K 线图数据量调研估 28 MB,正式版 50.6 MB | 估计在实测后如实更正,并给出可选的优化 |
| 默认排序把天天砸穿下轨的票排在最前 | 本地预览要真点、真排,测试覆盖不到人的眼睛 |
最后一条值得多说一句。均线通道上线前,所有测试都绿着,可在浏览器里一点,默认排序把一路暴跌、远在下轨之下的票排在了最前面;日期列点了不排,因为解析函数只认出了年份。这些问题测试不会发现,因为测试只检查程序有没有照设计做,不检查设计本身合不合人意。验收这一步必须有人,有眼睛,有手。
还有一条,是整个过程中最打动人的:承认不知道。成本报告里写「效率提升几成不知道」,台账里写「这一项需求方没说,我们先按默认做」,审计报告里给每个推算的数字标上「推算」。一个系统最可贵的品质,不是永远正确,而是你永远知道它在哪里可能不对。
10 · 举一反三:四根柱子,一副地基
把这三周的经验收拢,是这样一座屋子:

| 柱子 | 一句话 | 迁移到你的项目,先做这一件 |
|---|---|---|
| 流程 | 先写后做 | 下一个需求开工前,写一页纸:原话、理解、不做什么、验收标准 |
| 闸门 | 规矩写进程序 | 在部署脚本开头加一行:工作区不干净就退出 |
| 证据 | 对拍胜过自信 | 下一次重构前,把现有产物整份存下,改完逐字节比 |
| 分工 | 人定,机做 | 列一张口径台账;把部署那一步留给人 |
| 地基 | 架构克制 | 数据只留一个写入口;每加一个依赖,先问能不能不加 |
这五件事,单拎出来没有一件新鲜。需求单、发布闸门、特征测试、配置化,软件工程教科书里早就写过。新鲜的是语境:当写代码的成本被 AI 压到接近于零,这些老规矩的价值不降反升。从前写代码慢,慢本身就是一种闸门,人在敲键盘的间隙里自然会想一想;现在代码几分钟就出来,这道天然的闸门没了,只能靠人造的闸门补上。
工欲善其事,必先利其器。可器已经利到这个程度了,下一步要修的,是用器的规矩。
11 · 尾声:规矩是给自由修的路
回头看那张最初的阈值表,它现在还在系统的最深处,六个条件,三档市值,一个字没改。系统长大了十倍,可需求方最初的那份经验,被原封不动地供在那里,所有没说清的地方都记在台账上,等他来定。
这或许就是规矩的意义。它不是捆住手脚的绳子,而是让人敢跑快的路。有了闸门,才敢让 agent 放手去写;有了对拍,才敢在一夜之间重构整个数据底座;有了台账,才敢对需求方说:你没想好的,我们先替你记着,不替你决定。
从前写代码慢,规矩是一种奢侈。如今代码写得飞快,规矩成了刚需。也许下一个阶段,连规矩本身也会由 AI 来提议、由人来拍板。那就是另一篇文章了。
文中系统只做筛选与记录,不做收益回测,不构成任何投资建议。文中数字截至 2026-10-21,取自项目内部审计记录。