毕设旺季,后台问股票预测系统的同学又多了起来。大多数人上来就要“预测准确率高的模型”,但真正动手做毕业设计,你会发现一个残酷的事实:导师最在意的不是你的模型涨了几个点,而是你从数据清洗到策略回测再到论文成稿的整套闭环能不能讲清楚。这篇就把“Python股票行情预测系统”这个毕设方向从头到尾掰开揉碎,从技术选型、数据预处理、建模、量化回测,一直聊到最后源码、文档、PPT和答辩讲解怎么组织。内容偏实战,直接对着复制思路就能落地。
1. 系统设计与技术选型:为什么这套架构能撑起一个毕设
很多同学拿到题目第一反应是“先跑个模型”,然后陷入调包的泥潭。其实毕设考察的核心是完整度,也就是你懂不懂把一个问题从头到尾解决掉。股票行情预测系统这个题目,天然适合展示你处理“数据获取—特征工程—模型训练—策略评估—可视化展示”这条流水线的能力。
1.1 整体架构的分层设计
我的建议是把系统拆成四层:数据层、特征层、策略层和展示层。数据层负责对接行情源,拿到原始量价数据并做清洗;特征层负责把原始数据加工成模型能吃的特征矩阵;策略层是核心,包含预测模型和基于预测信号的交易决策逻辑;展示层则是把预测结果、回测曲线和持仓明细用图表形式呈现出来。四层各干各的,职责清晰,写论文时也好组织章节。
单说架构你可能觉得虚,具体到代码目录,我会这么说:
src/ data_fetcher.py # 行情数据获取与清洗 feature_engineer.py# 特征计算 models.py # 预测模型封装 backtest.py # 回测引擎 app.py # 可视化展示入口这套结构最大的好处是“哪里挂了改哪里”。比如换数据源,只动data_fetcher;换模型,只动models。答辩时老师问“我想换一个模型行不行”,你可以直接演示给他看,这是加分点。
1.2 为什么Python是首选而不是Java
选Python不是因为“大家都在用”,而是因为它在这个场景下确实碾压其他语言。处理行情数据要大量操作DataFrame,Python有pandas;训练序列模型有TensorFlow/PyTorch;做回测和可视化有backtrader、matplotlib。Java在这块的生态差太远,C++开发效率又太低。毕设的时间本就紧张,把开发效率拉满,把踩坑时间留给数据问题,这才是明智的选择。
1.3 数据源与存储怎么权衡
数据源我建议用公开的行情接口就好。我不提具体品牌,你去搜“Python A股行情库”,能找到好几个带免费额度的开源库。注册后用token调api,直接返回pandas DataFrame,非常省事。存储端的选择要注意,如果只是做日线级别的预测,每天2400多只股票也就是几万行数据,存本地csv或者SQLite绰绰有余,没必要上MySQL。等数据量到百万级,再考虑MySQL或者时序数据库。毕设的数据量,用SQLite能省掉一大把“数据库连不上”的破事。
提示:获取数据的第一步永远是先跑通一张表,而不是急着全市场拉数。我见过太多同学上来就想全量下载,结果被限流,卡了一整天。先拿一两只股票把链路跑通,后面批量只是循环的事。
2. 数据获取与预处理:行情数据的脏与净,直接决定模型下限
模型再牛,喂进去的数据是脏的,结果也是乱的。行情数据有两个大坑:复权处理和停牌缺失,这两个问题不解决,后面全白搭。
2.1 复权处理:不复权会算错收益
股票会分红、送股,导致价格出现“断层”。茅台从200元涨到1000元中间有除权除息的时候,价格直接往下跳,看起来像暴跌,其实持有者并没有亏损。做回测和预测,一定要用复权数据。
- 前复权:以当前价格为基准,调整历史价格,适合看历史走势。
- 后复权:以上市首日价格为基准,适合计算真实收益率。
做预测模型时我用的是后复权。为什么?因为前复权价格会随着每天行情变化而变化,昨天拉的数据和今天拉的数据,历史段价格对不上,模型结果没法复现。后复权的历史段是固定的,可复现性强,这对毕设论文来说太重要了。
2.2 数据清洗的三板斧
拿到原始数据后,先干三件事:去重、补缺失、过滤异常。去重没什么说的,按股票代码和时间排序,把重复行去掉。补缺失要注意,股票停牌的时候不会有K线,需要根据停牌天数决定是前向填充还是直接剔除。我的经验是,训练模型时剔除长期停牌的样本段,因为连续填充出来的假K线会干扰模型学习。而异常值过滤,重点看涨跌幅超限的记录,比如超过10%但没有事件支撑的,大概率是数据源错误,要做标记。
2.3 特征工程:怎么从量价数据里抽出模型能用的信号
原始数据的字段就几个:开高低收、成交量、成交额。纯靠这些直接喂进模型效果很差,要加工。我常用的特征分三类:
- 基础行情特征:收盘价、收益率、日内振幅、收盘位置。
- 技术指标类:均线MA5/MA10/MA20、MACD、RSI、布林带位置。这类能反映趋势和超买超卖状态。
- 统计类特征:近5日和20日的波动率、成交量的滚动均值、价格相对滚动均线的偏离度。
特征不是越多越好,反而是宁缺毋滥。特征多了维度就高,模型训练慢,还容易过拟合。我最终通常选12到15个特征,覆盖趋势、动量、波动、量能四个维度就够。
这里有个新手特别容易犯的错误:直接用全量数据计算滚动特征,然后在切分训练集测试集时不做处理。这会导致测试集里的特征用到了未来数据。正确做法是,计算特征的时候按时间先后顺序滚动计算,切分数据的时候直接按时间点切,训练集在前,测试集在后,绝不能让测试集的信息流入训练过程。
3. 预测模型与量化回测:把“预测”变成“策略”的完整路径
模型这部分是整篇博文的重头戏。很多同学用LSTM跑出一个MSE很小的值就兴高采烈,但导师一问他“这个模型的预测结果到底怎么用来赚钱”,他就卡住了。原因就在于他做的是预测,不是交易策略。预测和策略之间,隔着一整套信号转换和回测评估的逻辑。
3.1 模型怎么选:ARIMA做基线,LSTM做主力
毕设论文里一定要体现“对比”意识。不要只跑一个模型就交差,那样显得没有工程方法。我的做法是三个模型横向对比:
| 模型 | 类型 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|---|
| ARIMA | 统计模型 | 原理清晰、训练快 | 只能处理线性关系 | 作为基线模型 |
| LSTM | 深度学习 | 能捕捉长期依赖 | 训练慢、调参多 | 主力预测模型 |
| 随机森林 | 机器学习 | 抗过拟合、特征重要性可解释 | 不擅长时序连续性 | 效果对比 |
训练集和测试集的比例一般是7比3,而且必须按时间顺序切。我不建议像图像分类那样洗牌切数据,因为股票数据是强时序依赖的,打乱了就废了。
LSTM的输入是三维张量(样本数,时间步长,特征数)。时间步长我实验下来5到10天比较合适。太短模型看不到短期趋势,太长特征维度高、计算慢、也容易引入噪声。batch size取64或128,学习率从0.001起步,配合早停机制,一般40到60轮就能收敛。
注意:LSTM预测的标的我不建议直接预测价格,而是预测“未来N日的收益率方向”或者“涨/跌概率”。预测绝对价格是一个回归问题,误差会被波动放大,模型很难学。但预测方向是一个分类问题,更贴近交易决策的本质,模型也更容易收敛。
3.2 训练细节:早停、学习率、损失函数
LSTM训练有三大坑。第一个是过拟合,解决手段是早停(EarlyStopping)和Dropout,验证集loss多轮不降就停住。第二个是学习率太高导致loss震荡,建议配合ReduceLROnPlateau,当loss停滞时把学习率自动打五折。第三个是损失函数选择,预测涨跌概率用binary_crossentropy,预测收益率用mse,别混着用。
训练完之后,保存模型权重文件。注意,这个文件要放进毕设答辩的演示环境里,因为答辩现场没有时间让你重新训练!提前保存好,加载后直接推理,这是稳的做法。
3.3 回测:策略不能只停留在“预测准”
回测是展现工作量的一环。你预测模型做得再好,没有回测数据支撑,导师会觉得你只做了一半。回测逻辑要包含以下参数:
- 初始资金:100万,够演示但也不夸张。
- 手续费:单边万2.5以上,印花税卖出时千1,不能忽略。
- 滑点:按千1到千2模拟,不然回测收益会虚高。
- 调仓频率:不要每天调,用周频或者“信号触发才调仓”。
策略逻辑我推荐写一个简单又完整的版本:模型预测次日上涨概率,超过阈值(比如0.6)就买入一定仓位;持仓后如果预测转为下跌,就清仓,否则继续持有。再加上一个风控规则:单只股票亏损超过5%强制止损,账户回撤超过10%就空仓观望。这套规则别看简洁,跑出来的回测曲线给了你论文里可以放一整页的图表素材。
3.4 回测指标你会算吗
回测报告里必须有几个硬指标:累计收益率、年化收益率、最大回撤、夏普比率、胜率。这几个指标是导师和评委第一眼扫表格时关注的东西。
- 年化收益率:把累计收益折算成一年,公式是(1+总收益率)^(252/交易日数)-1。
- 最大回撤:回撤是当前净值距离历史最高点的最大跌幅,这个指标非常重要,因为回撤太大意味着策略离暴毙不远了。
- 夏普比率:衡量每承担一单位风险能换来多少超额收益,公式是(策略年化收益-无风险利率)/策略年化波动率。大于1算可以。
回测结果里有一点要特别小心,就是未来函数。比如调仓指令在T日收盘发出,你用的是T日收盘价计算信号,但实际成交价却用了T+1日的开盘价,这样回测结果会虚高。正确做法是信号在T日生成、T+1日执行,模拟真实交易中“看到信号再下单”的延迟。
4. 从源码到毕设交付:文档、PPT与答辩讲解的攻防要点
华而不实这一点在毕设答辩中是最致命的。你代码写得再花哨,文档一团糟,PPT放满代码,讲解时吞吞吐吐,前期的辛苦就全白费了。这部分的整理其实比写代码更耗心力,但它决定你毕设的成绩上限。
4.1 源码的组织:读起来比跑起来更重要
答辩老师拿到你的源码,不会真的去跑一遍。但他们翻目录结构时,第一感觉就影响评分。成熟的源码工程,目录命名要语义化,核心函数的注释要写“这个函数做了什么、输入是什么、输出是什么”。在README里写明:项目简介、环境版本(Python 3.8还是3.9,TensorFlow 2.x)、依赖清单、三步运行指南。不要小看这个README,很多同学丢分了就丢在这里。
4.2 文档怎么写:论文的骨架搭法
毕业论文结构我建议按这个框架走:
- 第一章 绪论:背景、意义、国内外研究现状。
- 第二章 相关技术:Python、机器学习理论基础、量化交易理论。
- 第三章 需求分析:功能性需求和非功能性需求,配上用例图。
- 第四章 系统设计:架构图、模块划分、数据库设计。
- 第五章 系统实现:核心代码片段说明、界面展示。
- 第六章 系统测试:模型评估指标、回测结果、界面功能测试。
- 第七章 总结与展望:你做了什么、哪里还能改。
每一章都要有图表支撑。架构图画用UML工具画,时序图也不要手画,直接画得规范些能省很多事。
4.3 PPT怎么取舍
PPT页数控制在12到15页。一个常见的叙事顺序是:题目背景、国内外现状、需求分析、总体架构、数据库设计、系统实现界面、模型结果展示、回测结果分析、总结展望。重点放系统实现和模型结果,每页只讲一个核心信息,切忌满屏代码。放一个小表格或者一张净值曲线图,都比堆代码强。
4.4 答辩讲解的套路
讲到模型的时候,一定要准备好这个问题的答案:“你这个模型怎么证明它有效?”你要答:不光看训练集MSE,要看测试集预测方向准确率,更要看回测出来的净值曲线和基准指数对比,同时我还跑了ARIMA对比,LSTM在方向准确率上平均高出X个点。这样回答既体现了对比思维,又体现了从预测到策略的闭环,这一段话是稳的。
再准备一个“被问到也不会慌”的弱项答案。比如老师问“那LSTM预测不准的时候怎么办”,你要说:所以我的策略不是每次都交易,阈值过滤加风控止损就是应对预测不准的工具,这也正是量化交易的逻辑所在,不追求每次都对,追求整体期望为正。
5. 毕设实战避坑实录:这些坑我帮你提前踩平
带过的同学里,几乎每个人都在下面这几个坑里栽过跟头。这一节就当一份排错手册,哪出问题翻哪里。
5.1 环境地狱:从TensorFlow到Python版本的纠缠
毕设时间点不同,TensorFlow和PyTorch的版本生态也不一样。如果你用的是新版Python,有可能装不上旧版TensorFlow,导致模型代码跑不起来。我的建议是大一统方案:用稳定版本组合,具体版本在你自己的实验环境里一次锁死。用conda创建独立环境,把依赖列表导成requirements.txt,连numpy的版本都锁住,保证打开就能复现。
5.2 数据停牌与退市风险警示的干扰
ST股、暂停上市股和普通股在行情规则上差异很大,有的甚至不连续交易。如果不加过滤,模型会学到一些并不存在的规律。训练前务必增加过滤条件:剔除ST股和上市不满60个交易日的新股。这类股票的涨停跌停价格计算方式都不同,与其让模型学习这种噪音,不如直接不碰。
5.3 回测净值曲线太顺滑的“凶手”
有同学回测曲线一路向上,漂亮得惊人。这种情况十有八九是遇到了滑点没扣除或者未来函数。还有个很隐蔽的坑是“用全样本做归一化”。你算归一化参数(均值和标准差)时用了整个数据集,包括未来段,这等于偷偷把未来信息透露给了模型。正确的做法是只fit训练集的归一化参数,把测试集按训练集的参数转换。这个细节很容易被忽视,但答辩老师可能一眼看穿。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 解决思路 |
|---|---|---|
| 回测收益率异常高 | 滑点或者手续费没扣 | 补充交易成本模型 |
| 训练loss不降 | 学习率过高或数据未归一化 | 调低学习率,检查特征尺度 |
| 预测方向准确率低于50% | 特征噪声过大或样本不均衡 | 增加趋势特征,使用类别权重 |
| 图表中文乱码 | matplotlib字体问题 | 设置中文字体文件路径 |
| 模型结果每次复现不一致 | 随机种子未固定 | 在代码里固定随机种子 |
5.5 时间预算分配
这是一条每个毕业生都值得听的经验。不要在前两周疯狂调模型,把数据管好、特征做好、回测误差磨干净,后段做PPT写论文的心态就不一样。可参考这个节奏:第1周跑通数据链路;第2到3周完成特征和基线模型;第4到6周跑LSTM和对比实验;第7周写文档和做PPT;第8周模拟答辩并打磨讲解。
我个人在实际操作中的体会是,这个毕设最大的价值不是那个预测准确率数字,而是你把一个模糊的“炒股能不能用AI挣钱”的想法,拆成了一个数据、模型、策略、评估四段式可验证的流程。掌握了这套流程,以后换任何标的、换任何模型你都知道该从哪个环节入手。最后再分享一个小技巧:答辩前预设一台不联网的环境,把数据和模型权重提前放到本地,所有依赖装好,演示时直接跑,把所有“网络请求超时”的意外都提前挡在门外。