news 2026/5/28 22:32:53

基于LSTM-Attention的股票价格预测与可视化平台

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于LSTM-Attention的股票价格预测与可视化平台

完整源码链接:https://pan.quark.cn/s/1e54aa2ae950

我*终于搞完了第二版,这次用的是真实数据直接从akshare拉,再也不用那个破几何布朗运动生成假数据了。上次导师看了一眼说"你这数据走势也太完美了吧,一看就是生成的",我当场尴尬得想钻地缝。行吧那就改成真实数据呗,结果这坑比我想象的深多了。

下面看下效果展示

先说说改了什么,原来的 data_generator.py 整个删了换成了 data_fetcher.py,用 akshare 库拉真实 A 股数据。然后 main.py 改成交互式平台了,启动之后能选股票,跑全部流程出7张图。visualize.py 加了第7张综合看板,一页集成所有关键信息。

先给你们看最终的项目结构:

2-基于LSTM-Attention的股票价格预测与可视化平台/ ├── data_fetcher.py # 真实数据获取 (akshare + 代理绕过) ├── model.py # LSTM + Attention (没动) ├── train.py # 训练 (微调) ├── predict.py # 预测评估 (微调) ├── visualize.py # 可视化 + 综合看板 ├── main.py # 交互式平台主入口 ├── requirements.txt └── charts/ ├── 000001_平安银行_price_trend.png ├── 000001_平安银行_pred_vs_actual.png ├── 000001_平安银行_attention_heatmap.png ├── 000001_平安银行_loss_curves.png ├── 000001_平安银行_error_dist.png ├── 000001_平安银行_future_pred.png └── 000001_平安银行_dashboard.png

好先说数据获取这块,他*的踩了一个史诗级大坑。akshare 这个库底层用的是 requests,而我的电脑上挂着****软件(C*la*h*),结果 requests 请求访问东方财富的 API,直接被拒连接。proxy 这个破问题折腾了我两天,查了各种资料最后发现在创建 Session 的时候把 proxies 强行设成 None 才行。

import requests _old_request = requests.Session.request def _new_request(*args, **kwargs): kwargs['proxies'] = {'http': None, 'https': None} return _old_request(*args, **kwargs) requests.Session.request = _new_request

这行代码必须放在所有 import 的前面,在 akshare 被加载之前就把 requests 给 patch 了,不然没用。还要额外清空环境变量:

os.environ['HTTP_PROXY'] = '' os.environ['HTTPS_PROXY'] = '' os.environ['http_proxy'] = '' os.environ['https_proxy'] = ''

这里有个坑是他的 agent 顺序问题,因为 akshare 自己内部也会 import requests,所以这个 monkey patch 必须在 import akshare 之前执行。我把这段代码塞到了 data_fetcher.py 最顶上,import 语句的前面,才总算把代理问题解决了。

然后还有个问题,akshare 获取全市场股票列表的那个接口ak.stock_zh_a_spot_em()经常抽风连不上,我加了缓存机制和兜底方案。缓存一个小时有效,如果接口挂了就用预设的 18 只热门股票。这 18 只够用了,平安银行、茅台、宁德时代这些。

PRESET_STOCKS = { '000001': '平安银行', '000002': '万科A', '000333': '美的集团', '000651': '格力电器', '000858': '五粮液', '002415': '海康威视', '002475': '立讯精密', '300750': '宁德时代', '600036': '招商银行', '600519': '贵州茅台', '600900': '长江电力', '601012': '隆基绿能', '601318': '中国平安', '601398': '工商银行', ... }

真实数据获取用ak.stock_zh_a_hist(),参数是 symbol(6位代码)、period(daily)、start_date、end_date、adjust(qfq 前复权)。前复权这个很重要,不调整的话分红送股会导致价格跳空,模型学到错误模式。

def fetch_stock_data(symbol, start_date, end_date, max_retries=3): for attempt in range(max_retries): try: time.sleep(random.uniform(0.15, 0.35)) df = ak.stock_zh_a_hist( symbol=symbol, period='daily', start_date=start_date, end_date=end_date, adjust='qfq' ) ...

随机延时 0.15 到 0.35 秒,加了三重重试,避免被东方财富封 IP。实测拉平安银行5年数据(1500多条)不到1秒就搞定了,速度还行。

数据拿到以后列名是中文的,得映射成英文。这里我当时没注意到「成交额」「振幅」「涨跌幅」这些列名返回可能有差异,不同股票返回的字段居然不一样!有的有换手率有的没有,所以用了一个字典映射,只在列存在的时候才改名。

rename_map = {} for old, new in [('日期', 'date'), ('开盘', 'open'), ('收盘', 'close'), ('最高', 'high'), ('最低', 'low'), ('成交量', 'volume'), ('成交额', 'amount'), ('振幅', 'amplitude'), ('涨跌幅', 'pct_chg'), ('涨跌额', 'price_change'), ('换手率', 'turnover')]: if old in df.columns: rename_map[old] = new df = df.rename(columns=rename_map)

技术指标加的跟之前差不多,MA5、MA20、波动率、成交量变化率、价格区间位置这些。但真实数据有个问题——缺失值多。因为股票有停牌、节假日不交易,rolling 窗口计算的时候会出现 NaN。比如刚上市的新股,前20天算不了MA20。所以必须 dropna,丢掉的数据有点多但没办法。

df['ma5'] = df['close'].rolling(5).mean() df['ma20'] = df['close'].rolling(20).mean() df['volatility'] = df['ret'].rolling(20).std() df['price_position'] = ((df['close'] - df['low'].rolling(20).min()) / (df['high'].rolling(20).max() - df['low'].rolling(20).min() + 1e-8)) df = df.dropna().reset_index(drop=True)

这里有个他吗的 bug 我找了半天,price_position 那一行我一开始写的是rolling(20'),多了一个单引号,Python 直接报 SyntaxError。我*这种低级错误 debug 了半小时才发现,眼瞎了属于是。

然后是主程序 main.py 改成平台化的交互模式,启动先显示 ASCII art 的 banner,然后列出18只热门股票让用户选。

平台分四个阶段跑:

  1. 获取真实行情数据
  2. 训练 LSTM-Attention 模型
  3. 模型评估
  4. 生成可视化图表(7张)
def run_platform(): code, name = select_stock() print(f"选定股票: {code} - {name}") df = fetch_and_prepare(code, years=5) result = train_model(df=df, feature_cols=FEATURE_COLS, ...) metrics = evaluate_model(...) # 生成7张图表 ...

训练的时候有个问题,真实数据比生成数据噪音大得多,模型收敛慢。用真实数据跑平安银行,Loss 从 0.49 降到 0.036(验证集),MAPE 大概 4.78%。4.78% 的误差看起来还行,但方向准确率只有 49.66%,几乎就是瞎猜。这说明模型学到了价格的平均水平但完全判断不了涨跌方向。这其实很正常,股票预测要是能超过 50% 的方向准确率,我还写什么毕设早去量化私募了。

看综合看板那张图(dashboard.png),一页集成了所有信息:

  • 左上大图是完整价格走势 + MA20 + 预测分界线 + 未来预测
  • 中上是测试集预测对比
  • 中中是注意力热力图
  • 中下是损失曲线
  • 左下是误差分布直方图
  • 中是散点图
  • 右下面板展示所有指标

Attention 热力图这张图还是挺有东西的,模型对不同的样本关注的时间段不一样。有的样本关注近期(最后几个时间步权重高),有的关注中期。说明 Attention 机制确实在学习不同的时间模式,不只是机械地看最后几天的价格。

未来30天预测那个图,因为用的是滚动预测,误差会累积。平安银行当前价格 10.76,预测30天后大概在 10.5 左右震荡。这种预测其实准确性存疑,但趋势方向可能有点参考价值。看历史数据的话平安银行从 2024 年开始就在 10-12 块之间横盘,确实没什么大波动。

有一次我训练贵州茅台(600519)的数据,MAPE 直接干到 2% 以下,因为茅台的走势太稳了几乎是一条斜线往上,模型学起来当然容易。

现在这版代码里有个问题我还没解决——获取全市场股票列表的 API 有时会超时。我加了每小时缓存的机制,第一次跑的时候如果列表 API 挂了就用预设的 18 只热门股作为备选,不影响正常使用。

还有个 bug 是数据量不够的问题。像科创板有些股票上市不到一年,数据量可能不到 120 条(60 条序列长度 + 至少 60 条训练),模型没法训练。data_fetcher 里我加了判断,不够的话自动扩大时间范围重试。

if df is None or len(df) < 120: start = end - timedelta(days=int(years * 365 * 2)) df = fetch_stock_data(symbol, start.strftime('%Y%m%d'), end.strftime('%Y%m%d')) if df is None or len(df) < 120: raise ValueError(f"无法获取 {symbol} 足够数据")

SimHei 字体的问题这次也遇到了,因为换了新电脑重新装的环境,matplotlib 又找不到 SimHei 了。plt.rcParams['font.sysfont']试了半天没用,最后确认必须是plt.rcParams['font.sans-serif'] = ['SimHei'],而且axes.unicode_minus必须设 False 不然负号显示异常。

总的来说这版用真实数据比之前的好太多了,至少答辩的时候能说"数据来自东方财富真实A股行情",听起来就专业。交互式选股的功能也让这个项目更像是"平台"而不只是一个脚本。而且真实数据的噪声和不确定性让结果更有说服力——MAPE 4.78% 不是完美的结果但真实可信。如果导师问"为什么方向准确率不高",标准回答是"股票市场受多种因素影响,单纯量价数据无法完全预测涨跌方向,这恰恰说明了市场的有效性"(笑)。

最后再强调一下,跑之前确保网络能正常访问东方财富的 API,如果挂了实在不行就用我预设的18只股票,也是国内最有代表性的公司了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 22:32:25

AI 英语在线考试系统

AI 英语在线考试系统在传统网络考试系统的基础上&#xff0c;深度融合了自然语言处理&#xff08;NLP&#xff09;、智能语音评测、图像识别和大数据的分析能力。这类系统不仅能解决“怎么考”的问题&#xff0c;核心更在于解决英语学科特有的“怎么评”&#xff08;尤其是听说…

作者头像 李华
网站建设 2026/5/28 22:30:47

Arduino超声波雷达制作:从硬件连接到Processing可视化全流程

1. 项目概述与核心思路拆解想自己动手做一个能“看见”周围物体的简易雷达吗&#xff1f;听起来像是高级实验室的玩意儿&#xff0c;但其实用你手边常见的Arduino开发板和一个小小的超声波传感器就能实现。这个项目本质上是一个极坐标扫描与测距系统的可视化呈现。它的核心思路…

作者头像 李华
网站建设 2026/5/28 22:30:30

别再只用sMRI了!ADNI fMRI数据预处理实战指南(基于Python/Nilearn)

从原始数据到特征矩阵&#xff1a;ADNI fMRI数据预处理全流程解析 在神经影像学研究领域&#xff0c;ADNI数据库已经成为阿尔茨海默病研究的黄金标准。但许多研究者下载数据后往往陷入困境——面对一堆.dcm或.nii文件&#xff0c;不知如何转化为可分析的格式。本文将彻底解决这…

作者头像 李华
网站建设 2026/5/28 22:26:30

降AI软件深度推荐2026年5月:知网维普AI痕迹精准去除指南

2026年毕业季过半&#xff0c;但还有大量同学的论文卡在AIGC检测这一关。知网在年初做了一次算法升级&#xff0c;维普、万方也在跟进&#xff0c;检测变得越来越严。论文一个字没改&#xff0c;去年12月查AI率18%能过&#xff0c;今年再查变成32%&#xff0c;很多同学就是栽在…

作者头像 李华
网站建设 2026/5/28 22:25:01

基于ESP32与WS2812打造实体战舰游戏机:从硬件集成到软件开发的完整实践

1. 项目概述&#xff1a;从零打造一台物理战舰游戏机几年前&#xff0c;我在一个创客展上看到有人用LED矩阵做了一个简单的井字棋游戏&#xff0c;当时就觉得这种将数字逻辑映射到物理光效上的交互方式特别有意思。后来在带学生做嵌入式项目时&#xff0c;总想找一个既能涵盖硬…

作者头像 李华