我编写的这两个量化交易程序每天都在长大,周六早起,继续干,终于更新了ETF基金轮动套利的程序,发给了轮动群的小伙伴们:基金套利,跟着AI学轮动策略

让大伙儿周六也开始卷起来

你追我赶,组队一起走才不累,才有干劲



当然我也不能闲着,继续优化程序的系统架构。 我的两个程序就像两棵小树苗,春天到了,每一天都在成长。我这个园丁开始面临一个棘手的技术债:早期的系统架构和命名规范,已经承载不了日益膨胀的业务需求。
前两天,套利监控系统正在经历一次从“单体工具”到“工业级双模基座(arbcore)”的大重构。系统目前拥有两个独立的生态:
在这个演进过程中,我发现了一个足以在未来引发灾难性 Bug 的隐患——底层数据库命名与概念的严重混淆。果然,我这个半路出家的编程门外汉,虽然有AI的加持,但是终究要露馅了。
今天就分享一下AI编程的强大,看看Gemini是如何给底层数据基座“把脉”,并制定全局“正名”与重构方案的。主要也是便于两个群里的伙伴们能更好地看懂我的程序,就容易进一步调试优化。
为了图方便,在早期的折价套利系统中,为了和无敌的网页保持一致,我将 3 个 A 股 ETF(159502、159518、513350)混入到了 LOFarb 程序的监控池中。这导致了一系列概念上的灾难:
lof_history_159502 的表名。如果这种概念混淆延续到新重构的 arbcore 核心基座中,多线程读写与数据大一统极易引发张冠李戴的致命报错。
顺便说一个我也刚刚学的"基金代码"知识点:上海交易所的ETF主要是51开头,56和58是新增的,深交所的ETF是159开头;上交所的LOF是501开头,深交所是16开头。
为了解决这个问题,奉行“业务纯粹性”原则:让 LOFarb 专心只做 LOF 折价套利监控,把 A 股 ETF 彻底剥离给 ETFRotate 子系统。
没有选择去代码里暴力删减ETF基金,而是利用系统成熟的“配置驱动”架构,直接在 LOF00 网页端控制面板中删除了这 3 个混入的 ETF。 当点击配置保存的那一刻,系统的自动化链路完美衔接:
lof_config.yaml 配置文件自动剔除这几个基金。业务剥离后,数据库里还残留着这 3 个 ETF 过去的对账数据。既然要交给 ETFRotate 轮动系统去管,且未来也要给它们做静态估值对账表,我编写了一个独立 Python 脚本,先将 SQLite 中遗留的表名平滑过渡:
lof_history_159502 -> 重命名为 -> etf_history_159502lof_history_159518 -> 重命名为 -> etf_history_159518lof_history_513350 -> 重命名为 -> etf_history_513350至此,历史资产交接完毕,LOFarb折价套利程序终于变得纯粹。
更深层次的挑战在于数据库"底层大一统表"的规范化命名。经过全局统筹,敲定了以下的重构蓝图:
核心思想:A 股公募产品统称为 **
fund**(囊括 LOF 和 A股 ETF),美股底层资产统称为 **usa_etf**。
lof_data 的“前世今生”在改名之前,对核心表 lof_data 进行了深度剖析:
price)、官方净值 (nav) 等。也就是“轮动群”和“折价群”的同学们用的是同一个数据库。
static_valuation.py 静态计算器极度依赖它,需要读取表里的 nav 和 price 结合汇率去算历史对账单。结论:将 lof_data 改名为 fund_data ,它装的不仅是 LOF,也装了 A 股 ETF。同理,etf_daily_prices 必须改名为 usa_etf_daily_prices 以防混淆。
虽然确定了完美的命名规范,但这属于“换心脏”级别的手术。改动这两张基准表的名字,意味着我们需要同时修改整个 arbcore 体系的关联链路。
以下是AI梳理出的全局重构清单,这时候发现AI的确牛逼啊,难道按照“预测”(瞎猜)大数据模型运作的机器代码竟然有这么强大的本事?
我经常在编程中恍恍惚惚,我面对是AI机器?还是真的一个专业的程序员?
etf_daily_prices -> usa_etf_daily_pricesarbcore/database/db_manager.py):修改 init_db 建表语句,修改 upsert_etf_price 方法名为 upsert_usa_etf_price,更新 cleanup_old_data 中的数据清理语句。ETFRotate/core/db_manager.py):同上同步修改,保持双基座一致。LOF011_daily_updater.py):抓取美股代码存库时,调用的 Upsert 方法名跟随更新。arbcore/calculators/static_valuation.py):核心 SQL 读取语句更改:SELECT date, price FROM usa_etf_daily_prices WHERE symbol = ?。LOF012_calculate_static_valuation.py):盘前诊断探针的 SQL 查询表名更改。lof_data -> fund_dataarbcore/database/db_manager.py & ETFRotate/core/db_manager.py):修改建表语句,将 save_lof_data 改名为 save_fund_data,同步更新更新估值、读取最新价格等内部 SQL。LOF011_daily_updater.py):存净值、存收盘价的方法调用更新,以及防重写的 SQL 查询语句更新。LOF012_calculate_static_valuation.py):透视打印日志中的 SQL 更改为 SELECT * FROM fund_data。arbcore/calculators/static_valuation.py):基石表的 Outer Join SQL 更改为 SELECT date, price as close, nav FROM fund_data WHERE fund_code = ?。为了彻底打通逻辑,如果 A股基金统称 fund,那么静态估值脚本 static_valuation.py 最后生成的历史对账表,其建表逻辑也需要从:table_name = f"lof_history_{fund_code}"升级为:table_name = f"fund_history_{fund_code}"这样一来,无论是 LOF 还是 A股 ETF 传入计算器,底层逻辑都将完全互通,不再有任何代码上的违和感。
“命名是编程中最难的两件事之一。”
在量化交易系统走向复杂、庞大、多模态演进的过程中,数据表的名称绝不仅仅是一个代号,它是业务逻辑与架构边界的具象化体现。
通过这次从“混杂”到“纯粹”的概念剥离与表结构深度梳理,底层 SQLite 数据库终于建立起了清晰的护城河。这不仅为后续的双模态(折价套利 + 轮动套利)同源推演打下了坚实的基础,也让这套系统真正具备了实际操作框架的整洁度。
感谢AI的大力加持!Gemini表现不错

