十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于机器学习的股票预测方法研究:从特征工程到时间序列验证

基于机器学习的股票预测方法研究:从特征工程到时间序列验证 简介这是一份基于机器学习的股票预测方法研究的论文文档格式为docx专为毕业设计、课程设计论文写作提供参考。内容系统梳理了股市预测两类主流方法其一仅利用历史股票数据涵盖分段线性表示、高斯过程分类、随机森林、支持向量机、卷积神经网络、长短期记忆网络、生成对抗网络等经典与深度模型其二引入金融新闻、社交媒体股民评论等非结构化文本通过事件结构化表示、情感极性分析等方式提升预测效果。全文从引言、方法综述到总结展望层层展开写作规范、逻辑紧密适合初学者、工程师、在校师生及毕业生借鉴学习。资源包共1个docx文件大小约35KB虽体积小巧但包含了摘要、关键词、细分方法对比与结论等完整论文结构。已有586人浏览学习可用于毕业论文或课程设计的重要参考建议仔细研读其中的知识点、方法脉络与实验思路切勿直接照抄。1. 这个标题真正要你做的东西不止是预测涨跌如果你在找《基于机器学习的股票预测方法研究》这个题目的资料大概率是正在写本科毕设、课程设计或者期末大作业。第一个需要认清的事实是这个题目的价值不在「预测准确率有多高」而在于你能不能给出一个完整、闭环、经得起答辩老师追问的研究过程。我见过太多人一上来就调 LSTM最后发现把数据随机打乱之后模型神准却在按时间顺序回测时被现实打脸。这篇文章会按照我实际带学生做这类题目的顺序来讲先处理数据和特征再选模型再做严格的时间序列验证最后说清楚论文里哪些地方最容易暴露问题。全程围绕机器学习做股票预测的最小可行路线不吹玄学不承诺收益只保证你每一步都有代码、有参数、有可复现的结果。明确一点你做的是研究性项目不是量化交易系统评价标准是方法正确、实验严谨、结论可信而不是赚了多少钱。2. 样本和特征怎么造做预测之前先回答一个问题2.1 原始数据拿到手先别急着建模股票预测本质上是时间序列预测我们面对的不是一串独立样本而是一根根按时间排列的K线。绝大多数新手翻车的第一步就是把股票数据当成普通表格数据随手一读就开始训练。后面第五章会专门说这个坑但这里要先建立正确的数据观。常见的做法是用 Python 的 pandas 直接读取日线数据一般包含这些字段date、open、high、low、close、volume。这类数据在网上很多不管是免费的证券接口还是金融数据网站格式大同小异。你需要关心的不是获取渠道而是字段含义和采样频率。主流的毕设选题用日线就够了分钟线数据量太大且噪声更多不好控制实验。数据准备的第一步是排序和清洗。排序很好理解时间序列必须按日期升序排列这点尤其重要因为后面要按位置切分训练集和测试集。清洗主要是处理除权导致的股价跳空。这个细节几乎每个学生都会遇到股票分红送股后价格会瞬间低开直接读取会让模型产生一个暴跌的假象。import pandas as pd df pd.read_csv(stock_daily.csv) df[date] pd.to_datetime(df[date]) df df.sort_values(date).reset_index(dropTrue) # 用前复权方式调整价格q 是复权因子不同数据源字段不同 df[close_adj] df[close] * df[q] df[open_adj] df[open] * df[q] df df.dropna(subset[close_adj])这里的核心逻辑是复权后的价格序列才能真实反映连续的价格变化模型学到的才不是除权缺口。参数上dropna 处理停牌缺失如果你拿到的数据源已经复权那这一步可以直接跳过。我一般会先画一张价格曲线图一眼看出有没有异常跳空。2.2 特征工程滞后特征是主角未来函数是红线特征构造是机器学习股票预测里最体现工作量、最容易得分、也最容易被答辩老师挑刺的环节。定义很清晰我们要用 t 日以及 t 日之前的信息预测 t1 日的涨跌任何用到未来信息的特征都叫未来函数一旦出现整个实验结果作废。常用特征分几大类直接来自行情的基础特征、由基础特征推导的技术指标、以及收益率序列的统计量。基础特征很简单比如开盘价、收盘价、成交量技术指标库很多talib 是个常见选择但毕设里我更建议用 pandas 手写几个核心指标因为答辩老师问起公式时你答得上来。# 收益率当前收盘相对于前一日收盘的涨跌幅 df[ret_1] df[close_adj].pct_change() # 5日和20日均线 df[ma5] df[close_adj].rolling(5).mean() df[ma20] df[close_adj].rolling(20).mean() # 动量过去5日累计涨幅 df[mom5] df[close_adj] / df[close_adj].shift(5) - 1 # 波动率过去20日日收益率的标准差 df[vol20] df[ret_1].rolling(20).std() # 标签下一交易日是否上涨用shift(-1)取未来数据 df[label_up] (df[close_adj].shift(-1) df[close_adj]).astype(int) df df.replace([float(inf), -float(inf)], float(nan)) df df.dropna()三个关键点。第一所有特征要么用 rolling 窗口要么用 shift 做滞后对齐确保 t 时刻的特征只含 t 及之前的信息。第二label 用 shift(-1) 取的是未来但标签本身不算特征泄漏因为标签就是你要预测的目标。第三pct_change 和除法会制造无穷大必须处理不然模型直接崩。每个特征之间实际上高度相关但树模型和线性模型对这个没那么敏感后面模型章节会展开。2.3 训练集测试集怎么切按时间顺序切而不是随机切数据准备好之后就是划分数据集。普通机器学习里用 train_test_split 随机划分是标准操作但股票数据绝不能这么做。原因很直接股票数据是串行相关的今天的股价和昨天高度相关随机划分会让模型看到未来片段测试集就成了开卷考试。train_size int(len(df) * 0.7) train_df df.iloc[:train_size] test_df df.iloc[train_size:] feature_cols [ret_1, ma5, ma20, mom5, vol20] X_train train_df[feature_cols] y_train train_df[label_up] X_test test_df[feature_cols] y_test test_df[label_up]按时间顺序切分的好处是贴近真实场景用 70% 的历史数据训练然后在剩余 30% 的未来数据上验证。导师问起来你这个逻辑完全站得住。参数上70/30 是常见比例数据量少时可以用 80/20时间跨度上最好把不同市场环境上涨段、下跌段、震荡段都包含进去否则模型只见过牛市测试集全是熊市结果没有说服力。3. 模型选型从线性回归到 LSTM每一层都要能讲清理由3.1 先跑通线性回归一个表现意外不错的基础线选模型之前先定性能基准这是机器学习项目里最基本的工程习惯。线性回归的好处是简单、可解释、几乎不会跑崩而且对预测下一日涨跌这类弱信号问题线性模型往往不比复杂模型差太多。from sklearn.linear_model import LinearRegression, LogisticRegression from sklearn.metrics import accuracy_score, mean_squared_error # 回归版本预测收益率数值 reg LinearRegression() reg.fit(X_train, train_df[ret_1].shift(-1).dropna()[:len(X_train)]) y_pred_reg reg.predict(X_test) mse mean_squared_error(test_df[ret_1].shift(-1).dropna()[:len(y_pred_reg)], y_pred_reg) print(线性回归 MSE:, mse)这里说的逻辑是线性回归拟合的是特征到未来收益率的线性映射它的系数代表每个特征的边际影响可以直接写进论文做解释。参数上没什么需要调的但要注意 X 和 y 的长度对齐shift(-1) 会造成最后一个样本的标签为空这点必须处理干净。MSE 作为评价指标是有问题的第五章会专门展开。既然任务是涨跌分类那更自然的选择是逻辑回归。它的输出是上涨概率阈值取 0.5 的时候刚好对应二分类论文里也更好写——你预测的不是涨多少而是涨的概率有多大。from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_s scaler.fit_transform(X_train) X_test_s scaler.transform(X_test) clf LogisticRegression(C1.0, max_iter1000) clf.fit(X_train_s, y_train) y_pred clf.predict(X_test_s) y_proba clf.predict_proba(X_test_s)[:, 1] print(逻辑回归准确率:, accuracy_score(y_test, y_pred))逻辑回归这里有两个参数值得讲。C 是正则化强度的倒数C 越小正则化越强默认 1.0 一般够用特征多或者共线性严重时可以调到 0.1 试试max_iter 设到 1000 是为了让模型收敛特征标准化后这个问题通常不明显。StandardScaler 对逻辑回归很重要因为正则化惩罚项的尺度受特征量纲影响不标准化的话均线和收益率这种数值差异巨大的特征会被正则化扭曲。3.2 树模型和梯度提升竞赛首选但在股票数据上要克制梯度提升树GBDT是机器学习表格数据上的常胜将军XGBoost、LightGBM 在各类比赛里几乎统治了结构化数据任务。股票特征以表格形式存在所以树模型自然是必试方案。但你在论文里需要说清楚为什么选树模型为什么结果可能不如预期。随机森林直接集成多棵决策树对特征量纲不敏感不需要标准化能捕捉特征之间的非线性关系梯度提升则是串行训练弱学习器每棵树纠正前一棵树的残差。从实现角度XGBoost 或者 sklearn 的 GradientBoostingClassifier 都行毕设用哪个取决于安装环境sklearn 不用额外装包演示成本最低。from sklearn.ensemble import GradientBoostingClassifier gbdt GradientBoostingClassifier( n_estimators100, max_depth3, learning_rate0.1, subsample0.8, random_state42 ) gbdt.fit(X_train, y_train) y_pred_gbdt gbdt.predict(X_test) print(GBDT 准确率:, accuracy_score(y_test, y_pred_gbdt)) print(特征重要度:, dict(zip(feature_cols, gbdt.feature_importances_)))三个参数值得写进论文。n_estimators 是树的数量100 是个起点树太多容易过拟合max_depth 是树的深度3 到 5 是股票数据的合理区间太深会把噪声都记住learning_rate 是学习率0.1 比较保守配合 n_estimators 一起调——学习率越小需要越多树。subsample 是随机采样比例0.8 表示每棵树只用 80% 的样本这本身就是防止过拟合的手段。树模型能输出特征重要性这是它相比神经网络的巨大优势。答辩时老师问你的模型学到了什么你可以直接回答过去5日动量最重要、波动率次之、均线类特征最弱。这种回答比空谈准确率有说服力得多。3.3 深度学习模型能写但别指望翻盘LSTM 在时间序列预测里被提到最多几乎每个股票预测相关的毕设都会想用它。实际结论可能会让很多学生失望在日线数据、手工特征这个设定下LSTM 很难稳定超过调好的 GBDT尤其是当你的样本量只有几百条的时候。但你依然可以把它作为对比模型写进论文证明你做了充分调研这个姿态本身就有价值。import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout # 构造时间窗口样本用过去20天的特征序列预测明日涨跌 def make_sequences(features, labels, seq_len20): X, y [], [] for i in range(seq_len, len(features)): X.append(features[i - seq_len:i]) y.append(labels[i]) return np.array(X), np.array(y) X_seq, y_seq make_sequences(X_train_s.values, y_train.values) X_test_seq, y_test_seq make_sequences(X_test_s.values, y_test.values) model Sequential() model.add(LSTM(32, input_shape(X_seq.shape[1], X_seq.shape[2]), return_sequencesTrue)) model.add(Dropout(0.2)) model.add(LSTM(16)) model.add(Dense(1, activationsigmoid)) model.compile(optimizeradam, lossbinary_crossentropy, metrics[accuracy])LSTM 的 input_shape 是时间步长、特征数时间步长 20 天是经验值代表模型看一个月的走势来做预测。Dropout 0.2 是防止循环神经网络在数据量小的时候严重过拟合。隐藏单元 32 和 16 是出于控制参数量的考虑这个规模的数据集用不了更大的网络。编译这里用 sigmoid 做二分类输出损失函数用 binary_crossentropy这个组合与逻辑回归是一脉相承的。3.4 模型对比的呈现方式不只比准确率论文里的模型对比表格直接决定答辩老师对你工作量的判断。不要只放一个准确率列至少要有这几个指标准确率、F1-score、召回率、在上涨样本上的召回率。尤其最后一项——如果模型把所有样本都预测为跌准确率可能也不低但明显没有研究价值。模型准确率F1上涨样本召回率上涨样本精确率逻辑回归????GBDT????LSTM????这里建议用测试集的预测结果填充这个表并写一小段分析哪个模型在哪个指标上占优、为什么。比如 LSTM 的准确率可能略低但对上涨样本的召回率更高这在宁可错过不可误判的场景下是另一个维度的能力。这种表格本身就是论文第三章或第四章的现成素材。4. 评估和回测预测对了方向不等于能赚到钱4.1 方向准确率和连续收益曲线才是有效信号准确率这个指标在股票预测里非常容易误导人。如果行情整体下跌测试期里下跌天数占多数一个永远预测跌的模型可能拿到 52% 的准确率看起来比随机猜测高一点实际毫无价值。所以方向准确率要拆开看上涨预测对了多少、下跌预测对了多少以及最重要的——方向准确率是否稳定超过 50%。回测的意义是把预测结果转化成如果按照这个预测去买卖收益曲线长什么样。那是一个很标准的实验import numpy as np # 策略预测上涨就持有预测下跌就空仓 positions np.where(y_pred_gbdt 1, 1, 0) daily_ret test_df[ret_1].values[:len(positions)] strategy_ret positions * daily_ret cumulative_strategy np.cumprod(1 strategy_ret) cumulative_benchmark np.cumprod(1 daily_ret) alpha cumulative_strategy[-1] - cumulative_benchmark[-1]核心逻辑是基准是买入持有策略策略收益是模型预测驱动。这里的平仓方式是下跌预测时空仓收益为 0如果把做空机制加进来会复杂很多毕设阶段不建议碰。alpha 是策略累计收益与基准累计收益的差正 alpha 说明模型有增量价值。注意收益率序列要对齐 positions 的长度标签 shift 造成的错位非常隐蔽。4.2 前推验证比单次切分更有说服力的实验设计70/30 的单次切分只能说明模型在某一时段有效答辩老师要是问换一段行情还行不行你就需要更扎实的验证方案。常见做法是滚动前推验证也叫时间序列交叉验证sklearn 提供了现成工具。from sklearn.model_selection import TimeSeriesSplit tscv TimeSeriesSplit(n_splits4) acc_list [] for train_idx, val_idx in tscv.split(X_train_s): X_tr, X_val X_train_s[train_idx], X_train_s[val_idx] y_tr, y_val y_train.iloc[train_idx], y_train.iloc[val_idx] clf LogisticRegression(C1.0, max_iter1000) clf.fit(X_tr, y_tr) acc accuracy_score(y_val, clf.predict(X_val)) acc_list.append(acc) print(各折准确率:, acc_list) print(平均准确率:, np.mean(acc_list))TimeSeriesSplit 的做法是第 1 折用前 25% 训练、下一段验证第 2 折用前 50% 训练、再下一段验证依此类推。这样每一折的测试段都在训练段之后不存在未来信息。这四个准确率如果都在 50% 附近波动说明模型不稳定你的结论要如实写在特定市场环境下具有弱预测能力而不是硬说模型好。这个验证逻辑是你论文里实验设计部分的亮点大多数学生想不到这一步。4.3 损失函数角度理解为什么预测难从机器学习角度看股票预测难是因为信号弱、噪声强。y 的方差大部分来自无法预测的随机成分模型能解释的部分占比很低。这反映在损失函数上就是不管你怎么调参损失下降都是平缓的验证集损失很容易反弹。所以我的建议是论文里不要回避这个问题直接写用均方误差作为回归损失时模型倾向预测接近 0 的收益率这就是弱信号问题的直观体现。逻辑上转折到分类问题上用涨跌分类替代回归是这类研究的标准取舍。这种分析在最终论文里反而成为加分项评阅人会认为他真的理解了自己做的东西。5. 避坑与常见问题排查论文翻车的五个高发点5.1 未来函数特征悄悄用了未来数据现象是训练时模型表现极好测试时说不通地差。原因是特征或者标签对齐出了问题。最常见的场景是计算均线时忘记用 shift、做滚动回归时窗口跨越了样本点、或者对全序列做了标准化后再切分——标准化这个操作本身就用了全序列的均值方差属于隐性未来信息。解决的办法是自检每一条特征构造代码确认只用到了当根K线以及之前的信息标准化只能先 fit 训练集再用训练集的参数 transform 测试集。我建议在写完特征后打印一条特征序列和原始数据的对比看一眼第 t 行的值到底由哪些日期的数据算出这一步就能过滤掉九成未来函数。5.2 用回归预测股价数值结果差到怀疑人生现象是预测的明日价格和真实价格曲线严重偏离甚至预测值长期停留在某个均值附近。原因是价格序列的非平稳性——今天的价格和 20 天前的价格高度相关回归模型学到的其实是价格等于上一日价格这种平庸解。解决的办法是预测收益率而不是预测价格。收益率是平稳序列可预测性和可解释性都更好预测出收益率后要用策略回测来判断价值而不是看价格曲线贴得有多近。这是这个方向上必须树立的最基本的建模观念。5.3 类别不平衡导致模型只会说跌现象是测试集上模型预测几乎全为 0下跌准确率却不算太低。原因是下跌天数占比约 55% 到 60%逻辑回归在默认阈值下为了最小化损失倾向预测多数类。解决的办法有三个层级。第一看混淆矩阵别只看 accuracy第二用 class_weightbalanced 让少数类获得更高的错分惩罚第三调整预测阈值比如只预测上涨概率大于 0.6 时才判为上涨虽然参与交易的次数变少但单次判断的可靠性提高。这在论文里写清楚是很成熟的实验改进思路。5.4 标准化时机错误测试集信息提前泄露现象是模型训练结果好得异常但按时间顺序回测却一塌糊涂。原因极可能是对训练集和测试集合并后做了标准化。StandardScaler 的 fit 会在全量数据上计算均值和方差测试集的分布信息因此被模型间接看到。解决的办法是先把数据按时间切分再在训练集上 fit scaler、用同一组参数 transform 测试集。代码结构上切分数据和特征工程最好是两个函数训练流程里先切分再进 pipeline这样答辩时逻辑也好讲。5.5 数据量不足以支撑 LSTM但论文里硬写现象是LSTM 的准确率比随机猜测还低训练集上却接近 100%。原因是样本只有几百根日线LSTM 参数量远大于样本量记住训练集易如反掌泛化无从谈起。解决的办法是要么增加数据频度用更长历史区间的日线要么用滑动窗口构造更多样本让序列截取数量增加到几千条要么诚实承认数据量的边界把 LSTM 作为探讨性实验。这几年毕设答辩老师对滥用深度学习基本零容忍诚实反而安全。6. 从预测到论文让实验结论站稳的三个细节数据和实验做完后论文的呈现方式同样决定成败。先说图表至少要画三张图特征相关性热力图、测试集预测概率分布图、策略累计收益曲线对比图。收益曲线对比图里画两条线一条是买入持有基准一条是模型策略肉眼可见的差距比任何统计指标都有冲击力。特征相关性热力图则能证明你对自己用到的特征做了充分了解。再一个细节是特征的滞后阶数。答辩老师经常问为什么用 5 日均线和 20 日均线不用 10 日和 30 日。我的习惯是做一个小实验把特征窗口参数改成几组不同值跑一遍对比准确率把结果放进附录。这不花多少时间但能显示出你在参数选择上是有实验依据的而不是随手填的。除此之外每个模型的参数表最好整理成一个统一表格写上参数名、取值、调整后效果这会让论文的实验设计部分像模像样。最后说说机器学习本身基本功的问题。这类论文答辩时老师很可能不会深究你的模型原理细节但一定会问一个所有机器学习任务都逃不开的问题你的模型有没有欠拟合或过拟合你是怎么看出来的。你要能用一句话回答训练集准确率远高于测试集是过拟合两者都低是欠拟合中间的标准是正则化项调参和验证曲线。建议去做一套小数据上的验证曲线实验横轴是树的深度或者正则化强度纵轴是训练集和测试集各自得分这个图放论文里任何答辩老师看了都会认可你的工程素养。做这个题目最深的体会是股票预测方向的研究性工作功夫更多在数据逻辑和实验设计上而不在模型本身。你要是把未来函数堵死、评估指标选对、对比实验做扎实哪怕最终结论是当前特征集下预测能力弱于随机水平论文也能立得住。反之模型再花哨时序划分一塌糊涂答辩现场必然露馅。希望这次梳理能帮你在毕设里少走弯路把时间花在真正有价值的事情上。本文还有配套的精品资源点击获取
返回列表