新闻详情

新闻详情

首页 / 资讯中心 / 详情

AI炒股系统实战:多Agent架构与LGBM双模型拆解

发布时间:2026/9/29 18:49:34来源:尧图网络
AI炒股系统实战:多Agent架构与LGBM双模型拆解
简介这是一套面向量化入门者与Python爱好者的轻量级AI炒股系统源码覆盖选股、风控、择时、复盘四个解耦模块并采用分类回归双LGBM模型既判断涨跌又预测涨幅。所有预测仅基于当日及之前数据无未来函数适合在普通笔记本上完成单票深度择时与周度复盘实验。资源包共11个文件以4个Python脚本主程序、训练、工具函数为核心附带两个训练好的pkl模型、两份csv交易/数据文件、两个pyc缓存及1个requirements.txt依赖说明整体仅598KB结构简洁便于二次开发。已有440人学习下载。通过该资源可快速搭建Streamlit交互界面点按按钮即可跑通选股与复盘流程是入门AI量化和扩展多Agent策略的良好起点。1. AI炒股系统不是黑匣子多Agent架构与LGBM双模型怎么落地入门量化时我总以为炒股系统是个黑匣子跑完回测只能看到一条漂亮的资金曲线。直到拆完这套源码才明白AI在这里被拆成了四个能单独调试的Agent配合LGBM分类与回归双模型既管择时也管周度复盘。它不需要庞大算力一个普通笔记本就能跑通核心解决的不是预测明天涨跌的玄学问题而是把“什么时候该操作、本周交易哪里不对”变成可回溯、可复现的函数。适合有一年Python经验、想验证AI择时思路而不是沉迷指标参数优化的交易研究者。读之前先确认你认识LGBM的train与predict接口剩下的跟着目录走。2. 多Agent架构与LGBM双模型为什么这么拆而不是写一个单脚本2.1 四个Agent的职责边界比单一大模型更可控我见过很多人做AI炒股系统时喜欢把数据下载、特征计算、信号生成、报告输出全塞进一个run.py跑完就完事。这套源码没有这么干而是用多Agent架构把流程切成了四个独立模块数据采集Agent负责拉取和清洗行情特征Agent负责计算指标与形态识别择时Agent负责调用LGBM分类模型输出信号复盘Agent负责在周末汇总本周交易并调用回归模型做持仓诊断。每个Agent之间只通过DataFrame和JSON传数据不传递自然语言这也意味着任何一环出问题你可以直接单独调试它而不是翻一个三千行的脚本。拿复盘Agent举个例子。它并不直接读取实时行情而是读取数据采集Agent落盘的历史行情文件、择时Agent写出的信号记录以及你自己补充的交易日志。三个输入一合并才生成周度复盘报告。这种解耦方式带来的实际好处是择时Agent换参数重跑复盘Agent不需要跟着改数据源换了其他三个Agent完全无感。提示如果你准备把这套代码改造成自己的策略研究框架优先保留Agent之间的数据接口协议而不是保留具体实现。2.2 LGBM分类回归双模型一个定方向一个定幅度为什么选LGBM双模型而不是用单个模型输出一个综合分数这里的逻辑很直接分类模型擅长回答“明天是涨还是跌”但它的输出概率不能直接当收益率来用回归模型擅长回答“未来五天大概能赚几个点”但对方向反转的敏感度弱。两者各有盲区组合起来才完整。具体来说分类模型用LGBMClassifier预测标签是明日相对今日的收益是否大于零输出概率作为择时信号的置信度。回归模型用LGBMRegressor预测未来五日累计收益输出数值用于仓位评估和周度复盘。训练特征完全共享同一份特征工程结果但评估指标不同分类看AUC回归看MAE与RMSE。这套源码把两个模型分开训练、分开保存预测时各自加载模型文件互不干扰。选LGBM而不是XGBoost或深度学习模型理由有三个。第一LGBM对表格型数据的拟合能力在中小样本上不会输给神经网络训练速度快到可以频繁重训。第二特征重要性输出很直观你能看到MACD、RSI、成交量这些因子到底谁在起作用而不是面对一个深度学习黑匣子。第三它对缺失值和异常值有一定容忍度行情数据里偶尔出现停牌导致的空值不用专门做太多清洗就能喂进去。2.3 源码目录与数据流一张表看清每个文件干什么刚打开压缩包时目录有点多我把关键模块整理成了下面这张表按数据流向排序训练时照着这个顺序跑不会乱。路径/文件名职责说明运行时依赖config.yaml全局配置数据区间、模型参数、阈值、标的列表无data_fetcher.py数据采集Agent下载日线行情并落盘为parquet行情接口feature_engineer.py特征Agent计算MACD、RSI、rolling统计与形态data_fetcher输出trainer_classifier.py训练LGBM分类模型输出模型文件feature_engineer输出trainer_regressor.py训练LGBM回归模型输出模型文件feature_engineer输出signal_generator.py择时Agent加载分类模型生成每日信号训练好的classifierweekly_review.py复盘Agent加载回归模型生成周度诊断报告训练好的regressorbacktest.py回测脚本按信号与次日开盘价模拟交易signal_generator输出整个数据流是一条单向链行情原始数据先经data_fetcher再进feature_engineer之后分叉到两个训练脚本训练产物再被signal_generator和weekly_review加载。没有循环依赖这也是它能被拆开调试的前提。运行时建议按顺序执行首次跑通后再考虑并行加速。3. 择时分析实战从MACD双底特征到LGBM分类信号3.1 特征工程把MACD双底/双顶变成模型能懂的数值热搜里“python源代码macd双底高低”指向的正是这个环节。MACD双底是经典的看涨形态但模型不认识K线图你得把形态翻译成数值特征。这套源码的做法不是直接传MACD柱序列而是提取出双底形态的关键要素DIF与DEA是否在零轴下方形成二次金叉、两底之间的最低点差值、第二次金叉时柱状体高度与第一次的对比。我把这部分特征构造代码简化如下def extract_macd_double_bottom(df, short12, long26, signal9): # 计算标准MACD三要素 ema_short df[close].ewm(spanshort, adjustFalse).mean() ema_long df[close].ewm(spanlong, adjustFalse).mean() dif ema_short - ema_long dea dif.ewm(spansignal, adjustFalse).mean() macd_hist (dif - dea) * 2 # 寻找MACD柱状体从负转正的拐点 cross_up (macd_hist.shift(1) 0) (macd_hist 0) cross_down (macd_hist.shift(1) 0) (macd_hist 0) features pd.DataFrame(indexdf.index) features[macd_dif] dif features[macd_dea] dea features[macd_hist] macd_hist # 近10日内是否出现零轴下方的金叉作为双底候选 features[golden_cross_below_zero] ( (dif dea) (dea 0) cross_up ).rolling(10, min_periods1).max() return features这段代码有个关键处理用shift(1)判断金叉拐点确保当前K线的信号只依赖之前的数据避免未来函数。参数short、long、signal是MACD标准值12、26、9对应日线级别最常用的配置如果你做的是周线级别可以改成26、52、12但样本量会明显减少需谨慎。rolling(10)的作用是把“过去10天内是否出现过零轴下方金叉”变成一个持久特征而不是只保留金叉当天为1这样模型更容易捕捉到二次金叉的延续性。除了MACD形态特征表里还叠加了RSI、布林带位置、过去5日和20日收益率、成交量相对20日均量的比值。这些特征全部用shift(1)对齐保证特征值在T日收盘后能计算且预测的是T1日行情。特征Agent每新增一个因子都要在最后拼接到主特征表统一对齐索引。3.2 分类模型训练正负样本、早停与类别平衡分类模型的目标是预测T1日收益率是否为正。训练前有一个容易被忽视的步骤划定训练集与测试集时绝对不能随机切分而是要按时间顺序切分。这套源码默认用前70%的交易日做训练后30%做测试并且保留了连续时间。标签构造采用future_return 0作为正样本跳过了收益恰好为0的极少情况。import lightgbm as lgb from sklearn.metrics import roc_auc_score # 按时间顺序切分不shuffle split_idx int(len(X) * 0.7) X_train, X_test X.iloc[:split_idx], X.iloc[split_idx:] y_train, y_test y.iloc[:split_idx], y.iloc[split_idx:] model lgb.LGBMClassifier( objectivebinary, learning_rate0.05, n_estimators1000, num_leaves31, class_weightbalanced, random_state42 ) model.fit( X_train, y_train, eval_set[(X_test, y_test)], eval_metricauc, callbacks[lgb.early_stopping(stopping_rounds50, verboseTrue)] ) print(Test AUC:, roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]))class_weightbalanced在这里很关键因为A股下跌和横盘的天数通常多于大涨正样本比例可能只有四成不平衡会逼着模型永远预测下跌。early_stopping监听测试集AUC连续50轮不提升就停止避免过拟合。num_leaves31默认值可以先用后面再调别一上来就开64或128否则你会在第五章节看到它怎么让你的回测翻车。训练完成后模型会保存为lgbm_classifier.txt后续signal_generator直接load。我一般会在训练脚本里加一行日志输出特征重要性Top 10方便和二次金叉特征的实际贡献对照。3.3 信号生成与滞后对齐提交预测结果给你“后悔药”择时Agent读取最新的特征表调用已训练好的分类模型输出每个交易日的上涨概率。信号不能直接当买卖指令因为概率值本身没有阈值概念。这套源码默认把prob 0.55定义为买入信号prob 0.45定义为卖出信号中间区域保持原有仓位不动。这个阈值可以在config.yaml里改但它影响的是误报率与漏报率的平衡。# signal_generator.py 核心片段 from datetime import timedelta import pandas as pd import lightgbm as lgb model lgb.Booster(model_filemodels/lgbm_classifier.txt) df pd.read_parquet(features/feature_table.parquet) # 只保留模型训练时见过的特征列避免列顺序错乱 feature_cols [c for c in model.feature_name() if c in df.columns] df df[feature_cols].dropna() # 预测的是次日信号日期列右移一天 df[signal_date] df.index timedelta(days1) df[buy_prob] model.predict(df[feature_cols]) df[signal] hold df.loc[df[buy_prob] 0.55, signal] buy df.loc[df[buy_prob] 0.45, signal] sell df[[signal_date, buy_prob, signal]].to_csv(signals/signal_log.csv, indexFalse)注意signal_date的处理模型用的是T日收盘后的特征对应的是T1日的交易决策所以把特征索引加一天这才是真正对账用的日期。很多自写回测在这里出错回测成绩好看实盘完全对不上核心原因就是没有做这个滞后对齐。signal_log.csv会同时记录日期、概率和信号这份文件也是随后复盘Agent的输入之一。4. 周度复盘模块回归模型、持仓诊断与Agent报告怎么串起来4.1 回归模型训练预测五日收益给仓位一个参考数字分类模型能告诉你方向但给不了“大概能赚多少”的参考。周度复盘需要量化每一笔信号的收益质量所以源码里设计了第二个LGBM模型直接回归预测未来五日的累计收益率。标签构造与分类模型不同分类用T1单日收益的符号回归用T1到T5的累计收益。这里要注意回归任务对异常值非常敏感遇到停牌复牌后的一字涨停收益率会拉到远超正常分布的水平训练前要做clip处理。# trainer_regressor.py 核心片段 df load_feature_table() # 构造五日累计收益标签clip到[-0.2, 0.2]抑制极端值 df[future_5d_return] df[close].pct_change(periods5).shift(-5) df df.dropna(subset[future_5d_return]) df[future_5d_return] df[future_5d_return].clip(-0.2, 0.2) split_idx int(len(df) * 0.7) train df.iloc[:split_idx] test df.iloc[split_idx:] model lgb.LGBMRegressor( objectiveregression, learning_rate0.05, n_estimators1000, num_leaves31, random_state42 ) model.fit( train[feature_cols], train[future_5d_return], eval_set[(test[feature_cols], test[future_5d_return])], eval_metricmae, callbacks[lgb.early_stopping(stopping_rounds50, verboseTrue)] )pct_change(periods5).shift(-5)的含义是T日那行数据记录的是从T1到T5这五天的总收益率。shift(-5)是把未来信息对齐到当前训练样本的特征行这在训练阶段是允许的因为你是在用特征预测未知的未来但绝对不能在预测阶段对尚未发生的数据做同样操作。clip(-0.2, 0.2)等效于把极端涨停跌停截断不然模型会被那几天的超常收益带走损失函数全消耗在拟合极端值上。4.2 复盘Agent把日志、建议与违规项拼成周报告每周五收盘后复盘Agent要做三件事读取本周信号记录、读取回归模型的预测收益、读取实际行情收益然后对比生成报告。它输出的不是一句“本周表现良好”而是一份包含表格和数字的诊断文档。源码里的报告格式是Markdown文件方便直接贴到文档或通知工具里。# weekly_review.py 报告主结构 report [] week_records signal_log[(signal_log.index monday) (signal_log.index friday)] for _, row in week_records.iterrows(): actual_5d price_after_5d(row[signal_date]) / row[close] - 1 pred_5d reg_model.predict(row[feature_cols])[0] report.append({ 日期: row[signal_date], 方向: row[signal], 预测五日收益: round(pred_5d, 4), 实际五日收益: round(actual_5d, 4), 偏差: round(pred_5d - actual_5d, 4), }) violations detect_violations(signal_log, trade_log) report.append({违规项: violations})这份报告的字段设计表如下你拿到源码后可以直接复用这个结构字段来源作用日期signal_log对齐交易事实方向signal_log判断做多/做空/观望预测五日收益regression模型复盘预期实际五日收益行情价格计算识别偏差偏差预测-实际衡量模型是否系统性悲观/乐观detect_violations是源码里比较有意思的函数它会检查是否在信号为sell时仍然持有、是否在buy信号次日开盘价高于信号价3%时强行追高。这些规则是写死在配置里的属于交易纪律的自动化检查。我建议你拿到源码后先把这里改成自己的交易规则因为模型输出了信号但执行层面的风险控制仍然依赖这些硬规则。4.3 报告怎么用从偏差里反推阈值设置复盘报告不只是用来回看它最实际的价值是暴露模型偏差。如果连续三周买入信号的真实五日收益都显著低于预测值说明分类模型的概率阈值给得太松0.55买入了太多低质量信号这时应该上调阈值到0.6试一轮。反过来如果信号数量太少、空仓时间过长说明阈值太紧。另一个常用做法是把偏差按年份聚合。A股不同年份的市场风格差异极大牛市里信号正确率高震荡市里又把把止损。源码里提供了一个analyze_bias_by_quarter函数按季度输出平均偏差和命中率看哪个季度模型表现滑坡再回头查那段区间的特征分布。这样做比总盯着总体准确率更接近实战因为AI炒股系统的信号最终要落到不同市场环境下宁可知道它会失效也别让它静默失效。5. 避坑排查数据、未来函数与Agent通信的五个教训5.1 未来函数回测曲线漂亮实盘瞬间翻车现象回测里年化收益喜人跑实盘或模拟盘时信号永远慢半拍收益曲线大幅回落。原因特征构造或信号生成时用到当日收盘后才知道的数据去预测当日结果最常见就是shift用反方向或者在生成T日特征时把T日收盘价也放进去了。解决全流程统一规则所有特征在T日计算时只能使用T日收盘前可得的信息。代码里强制检查每个特征列把凡是与close同期的列在预测前执行shift(1)再把T1信号日期加一天。我在signal_generator里加了断言如果特征表索引与信号日期重合直接报错退出。5.2 时间序列随机拆分训练集偷看了未来现象模型测试AUC高达0.85但换成滚动回测后AUC只有0.55差距巨大。原因训练集与测试集使用了随机切分同一个月内的样本被拆到了两边模型其实记住了行情形态的时间上下文而不是学到了真正的预测能力。解决一律按时间顺序切分且测试集必须晚于训练集。这套源码里split_idx int(len(X) * 0.7)是按行索引切的不是train_test_split随机切。如果你想做更严格验证改成按年份切比如2019到2022训练2023测试这样更能反映真实的前瞻性。5.3 LGBM过拟合num_leaves开太大噪声当信号现象训练集AUC接近0.99测试集AUC只有0.52特征重要性里排第一的居然是某个无意义的ID列。原因num_leaves128加上min_data_in_leaf5模型深度足够把训练集的每一条噪声都背下来量化特征里的微小波动全被当成规律。解决先把num_leaves降到31以下min_data_in_leaf调到20以上。然后用feature_fraction0.8和bagging_fraction0.8做随机采样逼迫模型找共性规律。我在调参时习惯先用默认参数跑一版只有测试集AUC超过0.6才考虑放宽复杂度否则优先怀疑特征是噪声而不是模型容量不够。5.4 Agent间传数据索引错位导致报告日期全偏现象复盘报告里的实际收益和信号日期对不上明明周一发的买入信号却显示周五才买入。原因三个Agent各自读取数据时日期索引的时区或格式不一致。数据采集Agent存下来的日期是2024-01-15 00:00:00复盘Agent用str.contains(2024-01-15)匹配而信号Agent输出的是2024/01/15字符串一拼接就错位。解决统一约定Agent间通信只传时间戳用pd.to_datetime规范化后再比较。我在源码里保留了一个normalize_datetime工具函数所有Agent入口都调它确保日期在进入逻辑前已经统一格式。如果你的数据源跨了多个市场或时区这一步省不了。5.5 复权方式不一致除权除息日之后信号全乱现象某只股票在6月除权后模型连续三天给出强烈卖出信号但实际股价并没有明显下跌。原因特征计算用了前复权数据行情落盘时却用了未复权价格除权导致的跳空被模型识别成暴跌信号。LGBM的回归模型对收益率的跳变极其敏感一个除权就能把预测值拉偏好几个点。解决全流程统一使用前复权价格且在数据采集Agent里就把复权处理做完后续Agent不再碰原始价格。adjustqfq是行情接口里最常用的参数如果你在data_fetcher里改了复权方式记得把训练好的两个模型全部重跑一遍旧模型对新的价格序列不生效。6. 进阶滚动训练与特征稳定性验证把系统从“能用”推到“敢用”6.1 每月滚动重训让模型跟上市场风格变化静态模型最怕市场风格切换2024年有效的因子在2025年可能变成反向指标。常见做法是每个月末用过去12个月数据重训一次模型并用最近一个月的样本验证。源码里预留了一个retrain_cron.py参数是训练窗口长度和重训频率我习惯设成window_days365, freq1ME。重训不是从零开始会延续上一轮的最优num_leaves和learning_rate这样超参数稳定特征重要性变化才可对比。6.2 特征稳定性检查只用两行代码确认因子没有失效每轮重训后我会额外跑一次特征重要性排序上周模型排名前五的特征本周如果跌出前十就要回去查原始数据是否出了问题。下面这段代码可以放在重训脚本尾部importance pd.Series(model.feature_importances_, indexfeature_cols) top_features importance.sort_values(ascendingFalse).head(5) print(当前Top特征:, top_features.index.tolist())只有那些在连续三轮重训里都保持高重要性的特征才值得被写进最终策略白名单。这套源码最合我心意的地方也在这——它把AI炒股从“一键跑出代码”拉回到“每天确认输入、每周检查输出、每月验证特征”的工程节奏里。多Agent架构让每一步都可以单独重放LGBM双模型让方向判断和幅度判断各有数据支撑。以前我做策略总是回测完就扔进文件夹吃灰从那以后我每次落地一套新源码都会强制走一遍先跑数据流、再核对信号日期、最后跑一个滚动重训的三步流程确认每一步都对得上账才敢把它放进模拟盘。希望这些拆解能帮你在自己的数据集上少走几趟弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

IOMMUFD脏页跟踪与Dirty Bits读取实现详解 2026/9/29 19:53:05

IOMMUFD脏页跟踪与Dirty Bits读取实现详解

一台物理机上跑了三台虚机,其中一台绑定了万兆网卡,迁移这台虚机时,QEMU 能通过 KVM 把普通内存的脏页抓得清清楚楚,但设备 DMA 写过的页面它在 KVM 侧根本看不到。这些年做设备直通迁移踩过最深的一个坑就是“CPU 看到的干净页&a…

阅读更多 →
FP7195升降压LED驱动设计:宽输入恒流精度与EMI优化实战 2026/9/29 19:53:05

FP7195升降压LED驱动设计:宽输入恒流精度与EMI优化实战

1. 项目概述:为什么FP7195成了中小功率LED驱动的“稳压锚”最近三个月,我陆续接手了6个工业照明改造项目,客户清一色提同一个要求:“灯珠要亮得稳,调光不能闪,输入电压波动大时也不能掉流。”——这背后其实…

阅读更多 →
Claude Code插件机制全解析:从官方市场到高频报错排查 2026/9/29 19:52:58

Claude Code插件机制全解析:从官方市场到高频报错排查

老规矩,先给结论: claude-plugins-official 不是一个“下载完装上就能用”的普通插件包,它是 Claude Code 整套插件体系的实际入口。你能在社区里看到的那一堆问题——什么 harness failed to load plugins 、 plugins 加载失败但不知道…

阅读更多 →
WeChat AHP:Windows下VS Code深度集成微信的语义桥接方案 2026/9/29 19:52:58

WeChat AHP:Windows下VS Code深度集成微信的语义桥接方案

1. 这不是“连微信”,而是把微信变成VS Code的原生终端——WeChat AHP到底在解决什么问题? 你点开VS Code,右下角突然弹出一个绿色小图标,点击后,微信窗口直接嵌入编辑器底部面板,聊天记录实时滚动&#x…

阅读更多 →
N0-TWAM:7B触觉世界模型如何破解接触富集操作难题 2026/9/29 19:52:58

N0-TWAM:7B触觉世界模型如何破解接触富集操作难题

说实话,当我看到“复旦NeoteAI首发N0-TWAM”这个消息时,第一反应是:世界模型这波,终于开始碰真问题了。过去一年里,我们见到的世界模型大多是视频预测、游戏智能体、自动驾驶场景,它们对“看”这件事很擅长…

阅读更多 →
Claude Code插件机制详解:从官方仓库到环境配置与报错排查 2026/9/29 19:52:58

Claude Code插件机制详解:从官方仓库到环境配置与报错排查

如果你最近折腾过 Claude Code,大概率见过claude-plugins-official这个项目名,或者至少被一堆报错糊过脸:harness failed to load plugins、claude 无法识别 cmdlet、claude needs the virtual machine platform on windows……这年头玩 AI 编…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉