使用MATLAB预测股票次日股价实战

数据获取、特征工程、时间切分、神经网络集成与诚实评估

实验数据截止:2026年6月24日

本文使用 MATLAB R2025b、Tushare 日线行情和 fitrnet 神经网络,对深南电路 002916.SZ的下一交易日收益率进行预测。重点不是展示一条“神奇曲线”,而是完整说明数据处理、时间序列切分、特征工程、模型选择、集成预测、朴素基线和结果局限。

建议标签: MATLAB、Tushare、A股、神经网络、量化分析、时间序列、股票预测

一、项目背景

股票预测最容易出现两个误区:

  • 直接拟合不断上涨的价格,使模型只学会长期趋势;
  • 随机打乱训练集和测试集,让模型在训练时“看到未来”。

因此,本项目没有直接预测股价绝对值,而是预测下一交易日的对数收益率:

y(t) = log(Close(t+1) / Close(t))

预测出收益率后,再用当天收盘价还原下一交易日价格:

ForecastClose(t+1) = Close(t) × exp(y_hat(t))

这样既能减弱价格非平稳趋势的影响,也方便与“明天价格等于今天”的朴素基线公平比较。

图:模型总体流程

二、运行环境与项目文件

本文实验环境如下:

项目

配置

MATLAB

R2025b

数据源

Tushare 日线行情

股票

深南电路 002916.SZ

历史范围

2017-12-13 至 2026-06-24

有效日线数量

2065 条

建模函数

`fitrnet`

预测目标

下一交易日对数收益率

项目核心文件:

E:\A股\
├─ tushare_matlab_sdk\
├─ data\002916_daily_raw.csv
├─ fetch_shennan_history.m
├─ analyze_predict_shennan.m
├─ generate_blog_figures.m
└─ analysis_results\

三、通过 Tushare 获取历史行情

Tushare MATLAB SDK 原始版本较老,内部使用的 urlread2 已不适合当前 MATLAB 和 HTTPS 接口。因此我将网络层改成 MATLAB 自带的 webwrite,同时保留原有调用方式:

token = string(getenv("TUSHARE_TOKEN"));
api = pro_api(char(token));

data = api.query("daily", ...
    "ts_code", "002916.SZ", ...
    "start_date", "20171213", ...
    "end_date", "20260624");

Token 不写入源代码,而是放入当前 MATLAB 环境变量:

setenv("TUSHARE_TOKEN", "你的Tushare Token")

这种方式可以避免将密钥提交到 Git 仓库或者截图中。

原始数据包含:

  • 开盘价、最高价、最低价、收盘价;
  • 前收盘价和涨跌幅;
  • 成交量与成交额;
  • 交易日期和证券代码。

四、为什么要重建连续价格

A股会发生送股、分红、拆分等除权除息事件。若直接对未复权收盘价求差,模型可能把机械除权误认为真实暴跌。

本文利用 Tushare 返回的日涨跌幅重建连续价格序列,并将最新价格作为锚点:

dailyReturn = log1p(T.pct_chg / 100);

logContinuousClose = zeros(height(T),1);
logContinuousClose(end) = log(T.close(end));

for k = height(T)-1:-1:1
    logContinuousClose(k) = ...
        logContinuousClose(k+1) - dailyReturn(k+1);
end

continuousClose = exp(logContinuousClose);

这个连续价格用于计算均线距离和趋势特征;最终预测价格仍然以最新真实收盘价为基准。

五、特征工程设计

模型共使用 15 项特征,所有特征都只使用预测时点及之前的数据。

1. 动量特征

  • 1日、3日、5日、10日、20日累计对数收益率;
  • 描述短期和中期价格惯性。

2. 均线偏离特征

  • 当前连续价格相对 MA5、MA20、MA60 的偏离;
  • 用于识别短线跌破均线或中期过热状态。

3. 波动特征

  • 5日收益率波动率;
  • 20日收益率波动率;
  • 当日最高价与最低价形成的日内振幅。

4. 强弱与成交特征

  • RSI(14);
  • 成交量对数变化;
  • 当前成交量相对20日平均成交量;
  • 开盘价相对前收盘价的跳空幅度。

核心代码如下:

XAll = table( ...
    dailyReturn, ret3, ret5, ret10, ret20, ...
    continuousClose ./ ma5 - 1, ...
    continuousClose ./ ma20 - 1, ...
    continuousClose ./ ma60 - 1, ...
    volatility5, volatility20, rsi14 / 100, ...
    logVolumeChange, volumeRatio20, intradayRange, openGap);

六、时间序列切分:绝不能随机打乱

样本按时间先后划分:

数据区间

比例

用途

训练集

70%

拟合网络参数

验证集

15%

选择网络结构和正则化参数

测试集

15%

最终样本外评价

nTrain = floor(0.70 * n);
nValidation = floor(0.15 * n);

iTrain = 1:nTrain;
iValidation = nTrain + (1:nValidation);
iTest = (nTrain+nValidation+1):n;

测试集时间约为 2025年3月25日至2026年6月24日,共302个交易日。测试集不参与网络结构选择。

七、网络结构选择

这是一个表格回归任务,因此采用 MATLAB 推荐的 fitrnet,而不是旧版的 fitnet 或 trainNetwork

候选结构包括:

architectures = {8, 16, [16 8], [32 16]};
lambdas = [1e-3, 1e-4];

每个候选网络都只根据验证集 RMSE 排名:

model = fitrnet( ...
    X(iTrain,:), Y(iTrain), ...
    Standardize=true, ...
    LayerSizes=architectures{a}, ...
    Activations="relu", ...
    Lambda=lambdas(l), ...
    ValidationData={X(iValidation,:),Y(iValidation)}, ...
    ValidationPatience=20, ...
    IterationLimit=500);

最终选中的结构为:

输入层:15项特征
隐藏层:32 → 16
激活函数:ReLU
L2正则化:0.0001
输出层:下一交易日对数收益率

八、为什么采用15个模型集成

神经网络的训练结果会受到随机初始化影响。对于股票这种噪声很高的数据,单次训练可能给出偶然的极端预测。

因此,最终阶段使用15个不同随机种子的同结构网络,并取预测中位数:

ensembleSize = 15;
ensembleReturns = zeros(ensembleSize,1);

for member = 1:ensembleSize
    rng(2000 + member);
    finalModels{member} = fitrnet( ...
        X, Y, ...
        Standardize=true, ...
        LayerSizes=[32 16], ...
        Activations="relu", ...
        Lambda=1e-4);

    ensembleReturns(member) = ...
        predict(finalModels{member}, latestFeatures);
end

nextReturn = median(ensembleReturns);

本次15个模型的预测收益率范围为约 -3.84% 至 +0.13%,标准差为1.23个百分点,说明模型对随机初始化仍然比较敏感。

九、必须设置朴素基线

股价预测图往往看起来很贴合,因为:

明天的价格通常与今天的价格非常接近

因此真正需要击败的基线是:

naivePrediction = 0;       % 下一日收益率为0
naivePrice = todayClose;   % 下一日价格等于今日价格

测试集结果

指标

神经网络

朴素基线

收益率 RMSE

3.953%

3.953%

价格 MAE

6.50元

6.46元

方向准确率

48.34%

随机方向约50%

图:样本外评估

结果非常重要:虽然预测价格曲线在视觉上紧跟真实价格,但模型没有稳定战胜朴素基线,方向准确率也低于50%。

这意味着该模型适合用作 MATLAB 时间序列和机器学习实验,不应直接作为交易系统。

十、2026年6月25日预测结果

截至2026年6月24日:

  • 最新收盘价:431.90元;
  • 当日涨跌幅:+1.38%;
  • 5日累计收益率:+6.94%;
  • 20日累计收益率:+3.58%;
  • 60日累计收益率:+82.58%;
  • RSI(14):62.48;
  • 相对MA20:+7.31%;
  • 相对MA60:+30.80%;
  • 20日年化波动率:75.43%。

集成模型给出的下一交易日预测为:

预测日期:2026-06-25
预测收盘价:423.80元
预测收益率:-1.87%
经验80%区间:407.62元至448.92元

图:次日价格预测

需要强调:经验区间由测试集残差的10%和90%分位数构造,并不是概率保证区间。

十一、为什么模型预测回调

为了理解预测结果,我进行了一次局部归因实验:

  1. 保持其他特征不变;
  2. 将某一项最新特征替换为历史中位数;
  3. 比较替换前后的预测变化。

图:局部归因

主要下行因素如下:

因素

模型解释

5日波动率偏高

当前短期波动率比历史均值高约2.2个标准差

跌破5日均线

最新价格仍低于MA5约2.43%

高于60日均线

最新价格高于MA60约30.80%,存在均值回归压力

日内振幅较大

6月24日日内振幅约5.56%,多空分歧较强

10日涨幅较高

短期上涨后,模型倾向给出回撤修正

其中,短期波动率是最大影响因素。若仅将5日波动率恢复为历史中位数,模型预测会由约 -1.9% 改善到接近持平。

但这属于模型关联解释,不代表现实中的因果关系。

十二、MATLAB预测图代码

以下代码绘制最近90个交易日价格、次日预测点和经验区间:

recent = T(end-89:end,:);
futureDate = datetime(2026,6,25);

figure(Color="w");
plot(recent.Date, recent.close, ...
    Color=[0.08 0.26 0.55], LineWidth=2);
hold on;

errorbar(futureDate, forecastClose, ...
    forecastClose-forecastInterval(1), ...
    forecastInterval(2)-forecastClose, ...
    "o", Color=[0.82 0.20 0.18], ...
    MarkerFaceColor=[0.82 0.20 0.18], ...
    MarkerSize=8, LineWidth=2);

yline(T.close(end), "--", "最新收盘价");
grid on;
xlabel("交易日期");
ylabel("价格(元)");
title("深南电路下一交易日收盘价预测");

十三、模型目前有哪些不足

1. 单只股票样本较少

2065条日线对于神经网络来说并不算多,模型容易学习到阶段性规律。

2. 市场状态会变化

训练期内有效的关系,可能在新的政策、产业周期和市场风格中失效。

3. 缺少外部变量

当前模型主要使用个股价格和成交量,没有加入:

  • 沪深300、电子行业指数和PCB板块走势;
  • 公司财务指标和估值;
  • 公告、新闻和机构一致预期;
  • 市场资金、北向资金和融资融券数据。

4. 评价优势不显著

模型在测试集上没有击败朴素基线。若把交易成本、滑点和涨跌停限制加入回测,实际表现可能更差。

5. 区间仍然很宽

407.62元至448.92元的经验区间说明单日噪声很大。相比点预测,风险区间更值得关注。

十四、可继续改进的方向

  • 使用滚动窗口或扩展窗口进行 Walk-Forward 验证;
  • 加入沪深300和行业指数的相对强弱特征;
  • 将预测目标改为“未来5日超额收益”;
  • 将回归问题改为上涨、震荡、下跌三分类;
  • 使用梯度提升树、线性模型和神经网络进行模型融合;
  • 加入交易成本后进行策略级回测;
  • 使用 SHAP 或置换重要性进行更系统的解释。

十五、总结

本文完成了一套较完整的 MATLAB A股预测实验:

  1. 使用 Tushare 获取深南电路历史行情;
  2. 根据涨跌幅重建连续价格;
  3. 构造动量、均线、波动率、RSI和成交量等15项特征;
  4. 按时间顺序划分训练、验证和测试数据;
  5. 使用 fitrnet 训练和选择神经网络;
  6. 使用15模型中位数降低随机初始化影响;
  7. 与“明天等于今天”的朴素基线比较;
  8. 输出点预测、经验区间和局部归因。

本次模型预测2026年6月25日收盘价约为423.80元,但测试集方向准确率只有48.34%,且未稳定战胜朴素基线。因此,最有价值的结论不是“明天一定下跌”,而是:

当前股价处于高涨幅、高波动和较大均线偏离状态,
模型认为短期回撤风险上升,但预测信号本身并不可靠。

免责声明:本文仅用于 MATLAB、时间序列分析和机器学习技术研究,不构成任何投资建议。股票市场存在较高风险,请独立判断并自行承担风险。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeBytes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值