夜雨聆风学习资料网

ARTICLE · 1017970

我让 AI 搭量化系统,它先给我画了张目录

我让 AI 搭量化系统,它先给我画了张目录
我让 AI 搭量化系统,它先给我画了张目录
我盯着输入框里那行字看了几秒,手指停在回车键上,没急着发。那是我第一次认真跟 AI 聊量化,背景是我一个写 Linux 和中间件十年的运维,对选股这事儿基本是白纸。我要的不是一段能跑的策略代码,是一张能把整件事装下的目录,加上每一层之间怎么对话。
我第一句话要的是目录,不是策略
为什么说目录,不先说策略。干运维的都明白一个理:接口和边界先定,里面怎么填,后面可以慢慢换。策略会变,今天用涨停板五维评分,下个月可能换成均线交叉,但"数据进来、因子算完、信号转指令、回测验过、风控卡一道、再出报告"这条主干不会变。AI 很擅长按你给的边界填实现,边界得你画。我见过太多 AI 一上来就吐几百行能跑的代码,跑通那一刻很爽,过两个月想改个打分逻辑,发现它把取数和策略揉在一起,牵一发动全身。第一句话给的是策略,它大概率给你一坨能跑但半年后没人敢动的代码;给的是分层和接口,它给你一套骨架,里面空着的地方明明白白写着"这里该填什么"。这种契约先行的做法,跟我们上线前先定配置格式、再写处理逻辑是一个路数。说直白点,就是先约定"你给我什么格式、我吐什么格式",两边的代码才不会因为一方改了字段就一起炸。
(我当时没想这么细,只是本能觉得先别让它写业务逻辑。)
落下来是这五层
那张目录实际落地的样子,是五层。
data/        取数 → Parquet 落盘 + DuckDB 查询 → 清洗复权strategy/    纯 pandas 技术因子 + 涨停板五维评分 + 信号转指令backtest/    T+1 开盘成交 / 双边 15bp / 涨跌停剔除 + 绩效评估execution/   模拟盘先行 + PTrade 通道(等券商权限)+ 订单生命周期risk/        事前风控 + 全链路日志 + 钉钉/Server酱告警
为什么是五层,不是塞进一个脚本。干运维的看系统,最怕一处改了别处跟着炸。把取数和策略分开,哪天 akshare 限频凶了,我只动数据层或者切到 mootdx,选股那套逻辑一个字不用碰;把回测和执行分开,实盘通道没下来之前,回测照跑,不影响前面选股。分层不是为好看,是给以后留改动的空间,哪一层要换,关掉那一层的门就行。
数据层我让它接 akshare 和本地通达信(mootdx),落盘用 Parquet,查询走 DuckDB,复权在清洗阶段做一次,做早了,后面因子算出来的收益率才不会被分红送转带歪。这一层是地基,我花力气把接口卡死,因为上面的策略、回测全都假定"喂进来的日线长一个样"。策略层只放纯 pandas 写的因子和评分,刻意不碰任何会联网的东西。回测层把成交假设钉死:T+1 开盘撮合、双边各 15bp 手续费、涨跌停那天剔除。执行层我先要模拟盘(本地按协议撮合的那套),实盘通道留着;日常真正要买要卖,我走的是券商App自带的模拟炒股,单子落在模拟账户上,全流程不碰真钱。风控层埋事前规则和告警出口。报告层专门交代了一句红涨绿跌,A 股惯例,不交代 AI 会按欧美习惯给你绿涨红跌。
入口就一条命令
run_pipeline.py 一共 349 行,把数据、选股、回测、风控、委托、报告、告警七件事串成一条命令:
python run_pipeline.py --date 20260909 --top 20 --history-days 20
参数我一个一个跟它磨过。--date 默认 auto,取最近交易日;--top 控制候选数量;--history-days 我最中意,设 0 就跳过回测,只跑当日选股,调试时省一大截时间;--min-score 是评分门槛;--paper 跑模拟盘撮合;--push 推钉钉或 Server 酱;--workers 并发取数线程数,代理环境下我一般压到 2,开高了 akshare 的连接会被掐;--no-cache 强制重拉。一条命令管住整条链路,比"打开三个 notebook 各点一遍"稳当得多,这也是运维的惯用法,能脚本化的别手点。
把整条链路收进一条命令,对我这种人意义不只是省事。上机器前先在本地跑通,确认每一层都正常出数,我才敢信它吐出来的选股结果;哪天结果不对,我能沿着这一条命令的日志一级级往回查,而不是对着三四个散着的脚本猜哪里炸了。出事怎么止损也清楚:参数写错顶多是当天选不出股,不会像手点那样漏一步还浑然不觉。
调参数这事儿也一样。数据源限频就缩 --workers,要重跑就 --no-cache,都是一行的事,不用重新排一整套流程。平时调因子我就用 --history-days 0 只跑当日选股,几分钟看一遍输出对不对,再开回测,迭代不用每次都等历史重算。真要出问题,日志会先告诉我卡在哪一环,是取数被限频,还是回测里某只票复权没对上,翻 logs/{YYYYMMDD}.log 一目了然,不用去翻代码猜。
换数据源,只改一行配置
数据源切换是个更硬的证据。我在 data/datasource/factory.py 里让它写了个 build_data_source(cfg),按配置里的一行 source 切四类实现:akshare(免费主源,独家有涨停池接口)、mootdx(本地通达信,快但不含涨停池)、composite(日线走通达信、涨停池走 akshare)、pandadata(账号还没下来)。切换只改配置一行,上面取数、选股、回测的调用代码一行都不用动。这就是接口抽象落地的样子:上层只认 get_daily / get_pool 这几个方法,底下换成谁无所谓。这事儿看着普通,但真到要换数据源的那天,你省下的是把取数、选股、回测三处调用全改一遍的功夫,那个改动最容易漏。
(我印象里通达信本地数据快,但缺涨停池,所以 composite 是折中。)
签名先定,实现后补
最硬的证据在 pandadata_ds.py。那时候 PandaData 的账号还在券商流程里,这条我没验过,具体哪天能接我不清楚,但我要求它先把这一层的三个方法签名写出来:
def get_daily(self, code, start, end):        raise NotImplementedError("PandaData 数据源待账号就绪后接入")def get_pool(self, date):        raise NotImplementedError("PandaData 数据源待账号就绪后接入")
注释里写着"账号就绪后把 TODO 换成真实 SDK 调用"。签名先定,实现后补,这就是我第一句话要求它的直接产物。它没因为实现没写就卡住整条链路,因为上层调的是接口,不是具体数据源。等账号真下来,我只填里面的实现,调用方一行都不用改,这也正是先定接口省下的后续功夫。
几条琐碎但要命的约定
基类那层还有几条约定我也逼它写死:DAILY_COLUMNS 和 POOL_COLUMNS 把列名定下来,所有数据源出来的表都对得上;normalize_code 把 sh600000600000.XSHG 这类前后缀统一成 6 位纯数字;standardize_board 把市场归一成 SH/SZ/BJ。这些东西单看琐碎,缺了上层就会各写各的,后面接数据对接对到怀疑人生。举个实际的,akshare 给的是 sh600000,mootdx 给的是 600000,不归一成 6 位纯数字,选股和回测两边对不上号,选出来的票回测里找不到,查半天才知道是代码格式在打架。
报告层我让它零第三方依赖,权益曲线用手写 SVG 画。技术因子那块也刻意用纯 pandas 实现 MA、MACD、RSI、ATR、BOLL、量能、动量,死活不装 talib,Windows 上编译那玩意儿是另一场噩梦,我可不想在装依赖上耗一个下午。这两处"不装"都是有意的:依赖越少,这台 Windows 机器上能跑的概率越高,真要挪到别的机器跑也少一道编译坎。
目录定太细的代价
写这段时我犹豫过一件要不要在文章里摊开的事。目录定得太细有个真实副作用:strategy/factors/technical.py 那个技术因子文件确实写好了,但选股主链路根本没 import 它。我是翻 selection 主文件时才发现 technical 从来没被引用,那个因子文件孤零零躺在 factors 目录里,import 列表里一个字没有。框架先铺了一圈,链路没接上。这不是编的漂亮话,是我这套"先定目录"做法会真实发生的坑,你把骨架画得越满,越容易先交出一堆看着齐整、其实没通电的房间。我现在的做法是反过来逼自己:每层建好当天,就让它在这条 run_pipeline.py 里被真正调到一次,跑不通就别往下写,宁可贵一点时间,也不攒一堆"文件在、没人用"的摆设。这一条我现在每天开工前都过一遍,看有没有建了没接的层。
落到磁盘上的东西
落到磁盘上的规模是实在的:182 个 parquet 文件,168 个日线、14 个涨停池快照,日线那批加起来 2.2MB,池子 256KB。产出物我让它固定六类:reports/report_{date}.html 是可视化日报,早上打开就能看昨天的选股和回测;reports/plan_{date}.csv 是次日委托计划,直接给执行层用;out/ptrade/DRYRUN_orders_{date}_pending.csv 是 PTrade 格式的待发单,现在还是模拟,权限下来能直接喂;两个 parquet 是落盘数据,复用时不重复拉;logs/{YYYYMMDD}.log 是全链路日志,哪层慢了、哪只票被风控拦了,翻它最准。有回 akshare 限频,我就是靠日志里那一串超时把 --workers 从 4 调到 2 的,没它我只能瞎猜。L4 那条实盘通道得等券商开通交易权限,走的是券商那边的流程,我催不动,所以现在执行层是模拟盘先跑着,权限下来再接 PTrade。权限没批的这段日子我要练手,就拿着系统出的计划去券商模拟炒股里下单,账户是模拟的,输赢也是模拟的,所以后面那些数字你当研究看就行,别当战绩。
下一步我想把 technical 那几个因子接进评分,再拿回测看看加权方式合不合理。这套骨架最大的好处是,因子换了不用动别的层,跑一遍 run_pipeline.py 就能看到新结果落在日报第几行。technical 那块我还在接,接上了我另写一篇。你要是手头有现成的纯 pandas 因子库,或者更顺的分层接法,在评论区留一句,我照着试。

相关学习资料

返回首页浏览学习资料