资讯动态

基于机器学习的A股走势预测系统源码全解析:从特征工程到回测落地

发布时间:2026/10/3 9:54:41 来源:尧图企业网站定制
简介一份面向股票投资者、量化分析师及机器学习初学者的A股走势预测系统完整包以历史行情数据为输入通过多种算法构建趋势预测模型解决人工选股与择时的主观性问题。压缩包共12个文件含6个Jupyter Notebook实验、3个CSV行情数据集、2个Python辅助脚本及1份README运行说明整体仅2.41MB。Notebook覆盖LSTM、SKlearn回测、傅里叶滤波处理股价序列、小市值结合盈利指标过滤策略等核心模块辅助脚本实现K线数据入库与特征工程数据集包含多只A股个股日线数据可开箱即用。已有519人学习下载。这套资源完整串联了“数据获取-特征构造-模型训练-回测评估”闭环并对A股T1、涨跌停等规则下的预测难点做了专门说明适合有一定Python基础、希望将机器学习落地到真实金融场景的开发者研习。1. 基于机器学习算法实现对A股股票走势预测这套源码到底能帮你做到哪一步做A股走势预测很多人第一反应是搞个LSTM或者XGBoost训练完一看准确率百分之五十五兴冲冲拿去跑实盘结果一个月亏掉半年工资。问题不在机器学习算法本身而在整个系统里数据、特征、模型、回测四个环节有没有闭环。标题里这套“源码数据集运行说明”的zip项目本质上是把一条完整的预测流水线打包给你让你拿到手不是看个demo而是能直接改参数、换模型、接实盘数据去迭代。它适合两类人一类是想把机器学习落地到金融场景的开发者另一类是已经有交易经验、想用算法辅助决策的量化爱好者。前者缺金融数据的处理经验后者缺工程化的建模流程这套系统恰好把两者的坑先踩了一遍。至于预测准确率能不能稳定超过五成五、收益能不能跑赢指数那不是跑通代码就能回答的问题需要你理解每一行特征是怎么来的、标签是怎么定义的、回测有没有作弊。接下来我把这套系统的源码结构、核心参数和常见翻车点逐一拆开讲。2. 读懂一套预测系统的源码数据模块、特征工程与模型选型2.1 zip包里通常装着什么目录结构决定工程习惯解压一个预测类项目zip之后第一件事不是看train.py而是看目录层级和文件命名。一个工程素养正常的项目至少会有这几个部分数据目录、特征脚本、模型定义、训练入口、回测脚本、运行说明文档。常见结构是stock_predict_ml/ ├── data/ # 原始行情数据、处理后的特征数据 ├── scripts/ # 数据清洗、特征生成 ├── models/ # 模型定义与训练脚本 ├── backtest/ # 回测与评估 ├── config.py # 全局配置 ├── requirements.txt └── README.md # 运行说明拿到源码先看data目录里有几份数据、格式是CSV还是parquet、时间跨度多长这些决定了你能不能直接复现。再看README里写的运行步骤是不是和脚本里的参数对得上很多项目写着“一键运行”实际跑起来缺这个依赖少那个字段。运行说明文档里一般会写python版本、依赖安装方式、训练和预测的入口命令。我在复现类似项目时习惯先创建新的虚拟环境不要直接用系统Python避免依赖冲突。2.2 数据模块A股行情的特殊之处必须单独处理A股行情数据和你熟悉的比特币分钟线、美股日线不一样它有三个必须处理的问题复权、涨跌停、停牌。原始数据里如果只有不复权价格那除权除息日附近会出现假跳空模型会学到莫名其妙的“暴涨暴跌”规律。所以拿到数据先看有没有复权因子字段没有的话需要根据分红送转信息自己算前复权价。涨跌停处理也很关键股票涨停时你挂单买不进跌停时卖不出如果标签里包含一字板样本模型预测的“上涨”你根本没法交易。这份zip里的数据集如果自带清洗脚本优先跑一遍看看输出行数和原始行数差多少。我见过一个项目数据清洗后样本直接少掉三成原因是把上市前五天的数据全删了理由是次新股波动无规律——这个操作对不对另说但至少说明作者考虑了这个问题。数据对齐方面A股交易日历和自然日不对齐节假日、调休让日期处理容易出bug一般建议用tushare或baostock拿到的trade_date字段做左连接不要自己用pd.bdate_range生成交易日。2.3 特征工程技术指标不是堆得越多越好特征工程是这套系统里最花心思的部分。常见做法是把原始量价数据开盘价、收盘价、最高价、最低价、成交量、成交额转成一组技术指标比如RSI、MACD、布林带、ATR、换手率、量比再加上一些跨period的统计量像过去5日收益率、20日波动率。特征数量控制在二十个以内比较合适堆到上百个特征没有足够样本量很容易过拟合。标签构造决定了这是一个分类问题还是回归问题。源码里如果标签是label 1 if future_return threshold else 0那这是一个二分类threshold一般取0.02到0.05代表未来N日涨幅超过两个点就算正样本。N通常取5、10、20对应短线和中线。这里有一个关键细节标签和特征必须严格时间对齐特征用t日及之前的数据标签用t1到tN的收益。如果代码里用了shift(-N)却忘了丢弃最后N行就会引入未来函数回测结果虚高——这个问题后面避坑章节会展开。2.4 模型选型为什么源码里最常看到XGBoost和LSTM十大机器学习算法在不同场景各有优势但股票预测这类结构化表格数据上XGBoost、LightGBM这类梯度提升树是主力。原因有三点能处理特征之间的非线性关系、对缺失值有一定容忍度、训练速度快且支持特征重要性分析。如果是做短周期预测LightGBM往往比XGBoost更快且精度不差如果特征里带了大量文本类情绪数据才需要考虑深度学习模型。LSTM在这类项目里出现率高但它很容易过拟合而且训练速度慢调参成本高。源码里如果同时给了树模型和LSTM两套实现优先跑树模型的基线结果确认LSTM是否真的带来了提升。我的经验是日线级别预测树模型十有八九能跑到和LSTM接近的水平但训练时间和调参成本低一个量级。如果你的目标周期是分钟级或tick级LSTM的价值才会明显体现。3. 跑通最小训练流程从数据集到预测结果的可复现步骤3.1 环境准备与目录约定在动手跑代码之前先确认Python版本和依赖。大多数这类项目基于Python 3.8或3.9依赖一般包括pandas、numpy、sklearn、xgboost或lightgbm、matplotlib。用虚拟环境隔离是最稳妥的做法cd stock_predict_ml python -m venv venv source venv/bin/activate # Windows用 venv\Scripts\activate pip install -r requirements.txt如果requirements.txt缺失或安装报错按项目实际需要的库单独装。pandas版本不要太高2.x在某些旧代码里会有方法废弃问题。装完后先跑一个最小的数据加载脚本验证环境可用# check_env.py import pandas as pd import xgboost as xgb df pd.read_csv(data/stock_data.csv, parse_dates[trade_date]) print(df.shape) print(df.head())这段代码的作用是确认数据文件能正常读取、日期列解析正确、依赖库都装到位。如果读取时报编码错误改成encodinggbk或encodingutf-8-sig这是A股CSV数据最常见的坑——很多数据集是用Excel导出的编码不是标准utf-8。3.2 数据清洗去除停牌、处理涨跌停与复权拿到原始行情数据后清洗步骤决定了模型学习的“天花板”。我通常会做以下操作剔除停牌日成交量为0的样本、剔除上市不满60个交易日的次新股、对价格序列做前复权处理、去掉极端异常值。# data_clean.py import pandas as pd df pd.read_csv(data/stock_data.csv, parse_dates[trade_date]) df df.sort_values([stock_code, trade_date]).reset_index(dropTrue) # 剔除停牌成交量为0或空值的直接扔掉 df df[df[volume] 0].copy() # 剔除次新股按股票代码分组保留上市满60天的样本 df[days_from_list] df.groupby(stock_code)[trade_date].transform( lambda x: (x - x.min()).dt.days ) df df[df[days_from_list] 60].copy() # 前复权用复权因子调整价格 if adj_factor in df.columns: df[close_adj] df[close] * df[adj_factor] df[open_adj] df[open] * df[adj_factor] else: # 没有复权因子时至少保证除权日不产生假跳空 df[close_adj] df[close]逻辑说明剔除停牌是防止大量0成交量样本干扰特征计算剔次新股是因为上市初期波动规律和成熟期差异巨大模型很难学到稳定模式复权处理保证价格序列连续避免除权缺口被当成真实的价格变动。参数说明days_from_list 60是一个经验值做短线预测可以放宽到30做中线建议保持60以上。3.3 特征与标签生成滑窗构造样本清洗完数据下一步是生成特征和标签。这一步是整个系统里最容易写错的地方核心风险在于特征里混入未来信息。安全做法是所有特征只使用t日及之前的数据计算标签使用t1到tN的收益。# feature_label.py import pandas as pd import numpy as np def generate_features_and_labels(df, feature_window10, label_days5, up_threshold0.03): df df.sort_values(trade_date).copy() # 特征过去N日收益率、波动率、量比 df[ret_1] df[close_adj].pct_change(1) df[ret_5] df[close_adj].pct_change(5) df[ret_10] df[close_adj].pct_change(feature_window) df[volatility_5] df[ret_1].rolling(5).std() df[volume_ratio] df[volume] / df[volume].rolling(20).mean() # 标签未来label_days日的收益率 future_close df[close_adj].shift(-label_days) df[future_return] (future_close - df[close_adj]) / df[close_adj] df[label] (df[future_return] up_threshold).astype(int) # 删除最后label_days行未来数据不存在 df df.iloc[:-label_days] # 删除包含NaN的行 df df.dropna().reset_index(dropTrue) return df调用方式df_feature generate_features_and_labels(df, feature_window10, label_days5, up_threshold0.03) feature_cols [ret_1, ret_5, ret_10, volatility_5, volume_ratio] X df_feature[feature_cols] y df_feature[label]参数说明label_days5表示预测未来5个交易日的涨跌属于短线预测up_threshold0.03表示未来收益率超过3%才标记为正样本你可以根据股票池的波动特性调整——波动大的股票池这个值可以设到0.05波动小的设到0.02。feature_window10控制特征回看窗口窗口太短特征容易受单日噪音干扰太长又会引入过多滞后信息。这里有一个易错点shift(-label_days)取的是未来第N日收盘价如果你用的是不复权价格遇到除权日这个收益会被扭曲。所以特征生成前一定要先做复权处理这也是为什么第3.2节的清洗顺序不可颠倒。3.4 模型训练与评估一组可靠的默认参数用XGBoost作为基线模型是这类系统里性价比最高的选择。下面这组参数可以作为起点# train_model.py import xgboost as xgb from sklearn.model_selection import TimeSeriesSplit from sklearn.metrics import accuracy_score, roc_auc_score # 时序交叉验证按时间顺序切分不能用随机K折 tscv TimeSeriesSplit(n_splits5) auc_scores [] for train_idx, test_idx in tscv.split(X): X_train, X_test X.iloc[train_idx], X.iloc[test_idx] y_train, y_test y.iloc[train_idx], y.iloc[test_idx] model xgb.XGBClassifier( n_estimators200, max_depth4, learning_rate0.05, subsample0.8, colsample_bytree0.8, reg_alpha1.0, reg_lambda2.0, eval_metricauc ) model.fit(X_train, y_train) y_pred_proba model.predict_proba(X_test)[:, 1] auc_scores.append(roc_auc_score(y_test, y_pred_proba)) print(fMean AUC: {np.mean(auc_scores):.4f})逻辑说明这里用TimeSeriesSplit而不是train_test_split因为金融时间序列有连续性随机打乱会让模型“偷看”到未来分布评估结果虚高。max_depth4控制树深度数值太大模型容易记住训练集噪音。reg_alpha和reg_lambda是L1和L2正则化系数在金融数据这种低信噪比场景下应该设大一些。subsample0.8表示每棵树只用80%的样本增加随机性减少过拟合。运行完这段脚本AUC在0.52到0.58之间是正常的不要期待0.8以上的值——那是特征里混入了未来函数。如果AUC低于0.5检查一下标签方向有没有可能你定义的“上涨”被写反了。4. 回测与模拟交易预测准确率高不等于能赚钱4.1 回测框架为什么不能直接按预测结果买卖训练出了预测模型下一步是把预测结果放到历史数据上模拟交易。很多人直接在预测DataFrame上加一列“预测上涨就买入”这样算出来的收益曲线有严重偏差忽略了交易成本忽略了涨跌停无法成交忽略了T1制度下当日买入不能卖出。正确的回测至少要包含这三个约束。常见做法是用向量化回测做初步验证再用事件驱动回测做精细评估。# backtest_simple.py import pandas as pd import numpy as np def simple_backtest(df, signal_colpred_proba, buy_threshold0.6, initial_cash100000, fee_rate0.0015, t_plus_1True): df df.copy() df[position] 0 df[cash] initial_cash df[holdings] 0 df[trade_date] pd.to_datetime(df[trade_date]) signal_col pred_proba buy_threshold0.6 fee_rate0.0015 t_plus_1True position 0 # 当前持仓股数 cash initial_cash stock_price 0 for i in range(len(df)): # 取当日开盘价作为成交价模拟次日开盘买入 open_price df.iloc[i][open_adj] pred df.iloc[i][signal_col] if position 0: # 买入条件预测概率超过阈值 if pred buy_threshold: # 计算可买股数留出手续费 max_shares int(cash / (open_price * (1 fee_rate)) / 100) * 100 if max_shares 100: position max_shares cash - max_shares * open_price * (1 fee_rate) else: # 卖出条件预测概率低于卖出阈值或触发止损 if pred 0.5 or df.iloc[i][close_adj] stock_price * 0.95: cash position * open_price * (1 - fee_rate) position 0 stock_price df.iloc[i][close_adj] df.loc[i, cash] cash df.loc[i, holdings] position * stock_price df.loc[i, position] position df[total_asset] df[cash] df[holdings] return df逻辑说明这段回测用每日开盘价作为成交价模拟“看到昨日预测信号后今日开盘买入”避免了用收盘价成交时的未来函数。buy_threshold0.6表示策略在预测上涨概率达到60%时才买入fee_rate0.0015是A股单边千分之一点五的佣金加印花税近似值卖出时也有费用。t_plus_1True这个参数在简化版里通过持仓状态隐式实现——当天买入后不会在同一天卖出因为每次循环只在持仓为0时买入、持仓大于0时卖出严格来说还需要进一步限制同一天内先买后卖的顺序问题这里可以看成一个基线版本。参数说明buy_threshold是你对模型置信度的要求阈值越高交易次数越少单笔盈利期望更高但机会成本也更高。stop_loss_ratio0.95是我加的一个硬止损条件回测里如果你不设止损一次大跌可能吞掉之前所有利润。4.2 回测结果怎么读三条曲线一个表格回测跑完后不要只看累计收益率。我一般会看四个维度年化收益率、最大回撤、夏普比率、交易次数。交易次数特别重要——如果你的模型预测了200次交易每次只能赚千分之几扣掉手续费后大概率是亏的。指标含义阈值参考年化收益率策略收益年化跑赢沪深300即可不要追求翻倍最大回撤从高峰到低谷的最大跌幅回撤超过30%说明风控失效夏普比率单位风险的超额收益大于1才算及格交易次数信号触发频次月均少于4次可能过度择时一个很容易忽视的问题是如果回测里交易次数多但每笔盈利很低大部分利润被手续费吃掉了。解决方法是提高买入阈值比如从0.6提高到0.7虽然交易次数减少但每笔交易的胜率和赔率都会提升。4.3 评估指标准确率、AUC与收益曲线的不一致预测模型的指标和交易系统的指标经常不对齐。模型AUC能达到0.6回测却亏钱模型AUC只有0.54回测反而赚钱。原因在于AUC衡量的是排序能力而交易系统更关心预测概率的绝对值——阈值设定、交易成本、持仓周期这些因素会完全改变结果。更关键的是AUC没有考虑预测错误的方向不对称性预测“上涨”错了直接亏钱预测“下跌”错了最多是踏空。所以评估模型时除了AUC还要看分阈值下的混淆矩阵特别是precision——预测上涨中真正上涨的比例。如果precison在0.6阈值下低于50%说明模型说“涨”的时候一半是错的系统无法盈利。5. 避坑指南A股走势预测最常见的5个翻车点5.1 未来函数回测曲线完美实盘一塌糊涂的元凶现象训练出来的模型AUC高达0.85回测收益曲线近乎直线向上但拉到实盘验证完全失效。原因特征或标签里混入了未来数据。最常见的是在计算技术指标时用了rolling窗口却忘了shift导致t日的特征实际上包含了t1日数据另一个常见问题是标签构造时没有丢弃最后N行模型在训练时看到了“正确答案”的轮廓。解决检查所有特征计算确认使用了shift(1)或更保守的方式保证只含历史信息。最直接的方法是构造一个“滞后测试”把特征整体向后平移一天重新训练如果AUC几乎不变说明原来的特征里没有未来信息如果AUC大幅下降说明有泄漏。5.2 前视偏差标准化和归一化用了全样本统计量现象模型在训练集上表现正常但时间序列交叉验证时前面的测试集AUC高得离谱后面的测试集AUC正常。原因对特征做标准化时用整个数据集的均值和方差去减而测试集样本已经参与了均值和方差的计算。解决标准化必须在每个时间窗口内独立完成只使用训练集数据计算mean和std对测试集用训练集的统计量转换。用sklearn的StandardScaler时是先在train_fold上fit再transform测试集不要在全量X上fit。5.3 幸存者偏差数据集里只剩活着的股票现象回测收益不错但实盘买入的股票经常是那些已经退市或ST的标的。原因有些数据集在构建时只保留了当前还在交易的股票历史上已经退市的股票被剔除了这导致策略永远在“幸存者”中选股自然会高估收益。解决拿到数据集先确认是否包含退市股票。如果只有当前交易列表回测结果只能当作“理想化上限”。处理方案是用历史某一天的全市场股票列表包括后来退市的来构建回测池。很多免费数据源不提供退市数据这是硬伤只能通过选择指数成分股来缓解——指数成分股本身有调入调出机制一定程度上覆盖了部分退市风险。5.4 涨跌停与停牌预测对了也买不进去现象模型预测某股票明天涨5%回测中确实买入赚到了钱但实盘当天一字涨停根本排不上单。或者模型预测会下跌但股票停牌了卖不出去资金被锁死。原因回测没有模拟涨跌停和停牌约束默认所有价格都可以成交但A股的实际交易规则决定了这些情况就是“看得见吃不到”。解决在回测代码中加入涨跌停过滤——当开盘价触及涨停价时认为买入操作失败当开盘价触及跌停价时认为卖出操作失败。同时统计停牌股票停牌期间持仓不计算浮动盈亏也不允许卖出。涨停价计算方式round(prev_close * 1.1, 2)ST股是5%限制科创板是20%。5.5 过拟合训练集AUC高测试集AUC回归均值现象训练集AUC 0.75验证集AUC 0.55时间序列交叉验证的每一折都相差甚远。原因模型复杂度超出了数据的信息量把噪音当成信号记住了。金融数据的信噪比极低你很难期望任何模型能做到持续高AUC。解决降低模型复杂度增大正则化系数增加特征筛选门槛。一个务实的做法是把数据集按时间分成三段第一段训练、第二段调参、第三段做最终验证第三段绝不参与任何调参过程。如果第三段AUC还能保持在0.54以上这个模型已经有初步实盘价值了。6. 把预测系统真正用起来的三个进阶技巧滚动训练、模型集成与概率校准这三个技巧能让系统从“能跑通”进化到“可持续迭代”。首先是滚动训练——不要用全量历史数据训一次就完事。市场风格在变三年前有效的规律今天可能失效。我习惯的做法是每两周用最近一年的数据重新训练一次模型配合滑窗验证模拟真实推理节奏。这种滚动策略会让AUC略有波动但模型的“新鲜度”能跟上市场变化。其次是模型集成与概率校准。单个模型的概率输出往往偏乐观——预测0.7的上涨概率实际只涨了55%。用CalibratedClassifierCV做Platt缩放可以矫正这个偏差。集成方面把XGBoost、LightGBM和随机森林的结果取均值或加权均值通常比单个模型稳定但收益不会大幅提升重点在于减少回撤。最后是把预测结果转成规则而不是直接下单。我个人的习惯是设一个预测概率阈值高于0.7才考虑买入低于0.4才考虑减仓中间地带一律不动同时单只股票仓位上限15%单日新建仓不超过3只。这些规则都属于预测系统的下游策略层跑通这套源码后花时间打磨这部分比反复调模型参数收益更大。这套流程走完你手里拿到的就不只是一个能出预测结果的脚本而是一套有约束、有验证、可持续迭代的决策辅助工具。希望这些经验能帮你在复现和改造这条预测系统的路上少走几个弯路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑