最近来找我咨询毕业设计选题的学弟学妹,十个里有六七个都把目光盯在了“股票行情预测”这个方向。今天要聊的这个题目,就是典型的代表:Django + LLM大模型股票行情预测系统 / 量化交易分析预测系统。这个题目之所以受欢迎,是因为它一个题目把 Web 开发、大数据处理、机器学习预测、量化交易回测、大模型应用全串起来了,既能展示代码功底,又能体现对前沿技术的理解,踏踏实实做完之后,对个人技术栈的提升也非常明显,这类系统现在确实是计算机和大数据专业毕设里的热门方向。
那这篇我就以过来人的身份,把从选题到答辩这一路会遇到的坑和关键决策一次性说清楚:这个项目到底怎么做、每个模块背后的“为什么”、数据怎么来、预测模型怎么选、LLM 怎么落地不显得牵强、回测系统怎么算指标,以及我亲身踩过的几个大坑。无论你是准备自己从零写,还是打算基于开源项目二改,这篇文章都值得收藏着看。
1. 先搞清楚题目想让你做什么
1.1 题目拆解:四个关键词背后的真实需求
你把这个题目扔给导师看,一眼看去是四个大词:Django、LLM 大模型、大数据、量化交易。但如果只是把四个词堆在系统里各管各的,答辩的时候导师三句话就能把你问倒。所以一开始就要想明白,这四个词之间应该是什么关系。
我理解这个项目的核心链路是这样的:用大数据的技术手段处理行情和新闻数据,用 LLM 大模型来做文本类数据的理解和情绪判断,用机器学习模型做价格或涨跌的预测,然后基于预测结果构建量化交易策略,最后用 Django 把这个全流程做成一个能登录、能操作、能看图表、能跑回测的 Web 系统。
在这个链路里,每个技术都有自己不可替代的位置:Django 是骨架,负责把数据、模型、策略、结果全部组织起来;大数据是手段,负责解决“数据量大、来源杂、清洗麻烦”的问题;LLM 是亮点,负责把传统预测系统里“没有语义理解能力”的短板补上;量化交易是落点,负责把预测结果转化为策略收益评估。这样形成一条完整的业务闭环,而不是四个孤立的功能模块。
毕业设计答辩最看重的是“逻辑自洽”。你选这个题目,第一个要能回答的问题就是:为什么需要 LLM?答案不是“因为前沿”,而是“传统股票预测系统只用历史行情数据,缺少对新闻、公告、舆情这些非结构化信息的理解,而 LLM 恰好擅长从文本中提取情绪和关键事件,可以作为额外特征注入预测流程”。把这个动机想明白,后面所有设计都会顺很多。
1.2 这个项目适合谁,能锻炼什么能力
如果你正在纠结选题,这个方向适合这几类人:
- 计算机科学与技术专业的同学:核心锻炼点是 Django 后端开发、数据库设计、前后端联调、系统部署,整套 Web 工程能力可以完整走一遍。
- 数据科学与大数据专业的同学:核心锻炼点是数据采集、数据清洗、特征工程、模型训练与评估,以及大数据的批处理思路。
- 想往量化金融方向靠的同学:可以深入了解技术指标、交易策略、回测评估、资金曲线这些概念,虽然毕设做不到实盘级别,但能把闭环打通,面试时是个很好的谈资。
反过来,如果你属于“完全没有 Web 开发经验、Python 基础也比较薄弱”的情况,这个题目对你来说工作量偏大。不是不能选,而是你要做好多花时间的准备。我自己带过的学生里,最短的从零基础到答辩做了两个月,平均每天有效编码时间大概四个小时左右。
1.3 毕设的交付物清单
这类题目通常的交付物包括以下四样,建议你在项目一开始就按这个清单规划时间:
| 交付物 | 内容 | 建议时间占比 |
|---|---|---|
| 源码 | Django 项目完整代码,包含前端模板、静态资源、数据库脚本 | 45% |
| 论文(LW) | 毕业设计论文,通常要求 1 万到 1.5 万字,含架构图、流程图、结果分析 | 30% |
| 答辩 PPT | 核心技术介绍 + 系统演示 + 测试结果 | 15% |
| 讲解/演示视频 | 录屏演示系统功能,配合论文使用 | 10% |
很多人喜欢先写完代码再写论文,我觉得这个顺序恰恰是反的。正确的做法是先花两三天把论文的大纲和系统架构图画出来,哪怕只是草稿,后面写代码的效率会高很多——因为你写代码时每一步都知道该往哪个模块里放,而不会写着写着发现某个功能前期没设计只好推翻。
2. 技术方案选型:每种选择背后都是有理由的
2.1 为什么后端用 Django 而不是 Flask 或 FastAPI
聊到这个题目里的 Django,很多人第一反应是“Django 太重了,Flask 更轻便”。但在这个项目里,Django 的重恰恰是优势。
这个系统需要的不是几个裸接口,而是完整的用户体系、后台管理、权限控制、数据库 ORM。Django 自带 Admin 后台,你可以直接把用户管理、股票列表管理、策略参数管理全部纳入后台,几分钟就能生成一套可用的管理界面,这在毕设答辩演示时非常加分——你可以现场演示“在后台添加一只股票,前端页面马上就能查到它的行情”。
另外,Django 的 ORM 对于操作 MySQL 非常友好,模型定义好后一条命令就能建表。它的迁移机制也能让你在开发过程中反复修改表结构而不至于崩溃。这对毕设这种需求经常互相打架的场景来说,体验好得多。
Flask 不是不能用,但你需要额外集成 Flask-Login、Flask-Admin、Flask-SQLAlchemy 一堆扩展,折腾下来并不比 Django 省事。FastAPI 在性能上确实强,但毕设并不需要那么高吞吐,而且 FastAPI 的生态在管理后台方面比 Django 差不少。所以我的结论很直接:做这种带后台管理功能的信息管理系统,Django 是省心选择。
很多人在热词里提到“Django 创建 app”“django 执行查询-删除对象”“Django RABC”,这些都是基础功。你只需要按常规建两个 app 就够:一个users管登录注册,一个analysis管行情、预测、策略和回测。
2.2 数据层的选择:MySQL + Redis + 数据仓库的取舍
既然题目里挂着“大数据”三个字,就有人会想“我是不是得上 Hadoop、Spark”。这里要泼一盆冷水:毕设项目里的大数据,一般指的是大数据处理思维和大数据工具链的合理运用,而不是非得上分布式集群。A 股全市场几千只股票、十年日线数据,撑死也就是几千万行,单机 MySQL 加索引完全扛得住。你非得搭一个三节点 Hadoop 集群,不仅浪费时间,而且很难在答辩现场稳定演示,到时候节点起不来直接翻车。
那“大数据”体现在哪?我建议在论文里这么写:数据体量达到数十万到上百万条记录,使用批量采集、增量更新、基于 pandas 的向量化计算进行清洗和特征处理,并通过后台任务队列实现异步处理,体现“大数据处理的工程思路”。这样既符合题目,又不给自己挖坑。
具体技术选型:
- MySQL 5.7/8.0:存储用户、股票基本信息、日线行情、新闻数据、预测结果、策略回测结果。
- Redis:缓存热门股票列表、预测结果,同时作为 Celery 的消息中间件。
- AKShare(免费开源财经数据接口):获取历史行情和实时行情。Tushare 需要积分,有些接口限制多,对毕设来说 AKShare 更友好。
- pandas + numpy:做数据清洗、计算移动平均、RSI、MACD 等指标,以及回测中的资金曲线计算。
- Celery + Redis:处理耗时任务,比如全历史数据回测、批量新闻抓取。
- ECharts:前端可视化,画 K 线图、预测对比图、资金曲线图、热力图。
这套技术栈的特点是:每个组件都有明确用途,没有一个是多余的,而且全部是免费开源方案,毕设经费为零也能跑。
2.3 LLM 大模型:到底怎么“大”法才能不落俗套
这是整个题目的灵魂,也是最容易翻车的地方。很多人一听“LLM 大模型”就开始琢磨“我要不要本地跑一个 7B 参数的模型”或者“要不要微调一个股票预测模型”。我的建议是:别在这上面死磕,把大模型当作能力组件接入系统,才是正确的姿势。
毕设场景下,大模型最多做好这三件事就够:
第一,财经新闻和股评的情感分析。用大模型给新闻标题或正文打一个情绪分数(比如 -1 到 1),这个情绪分作为特征进入预测模型。这一件事就能把 LLM 的语义理解能力和股票预测有机结合起来,在论文里你可以用“多模态因子融合”这种措辞来包装。
第二,股票综合分析报告生成。系统在跑完预测和回测之后,调用大模型生成一段自然语言的分析摘要:“该股票近 20 日趋势上行,MACD 金叉,情绪面偏乐观,模型预测未来 5 日上涨概率为 63%,建议关注风险:近期成交量放大伴随价格波动加剧。”这就是典型的 LLM 落地场景——结构化数据转自然语言。
第三,问答式诊断。用户在页面上输入“这只股票的市盈率和行业平均水平相比如何”,系统先查数据库,把结果丢给大模型,由它组织成通顺的回答。这对应了热词里“django python websocket实现后台有数据前端推送”的场景——你可以在页面上做一个交互式对话窗口,增强演示效果。
至于用什么模型,选择很多。如果调用云端大模型 API,国内有很多合规的选择,比如智谱、百度文心、阿里通义等提供的开放接口;如果为了“完全本地化部署”的卖点,也可以用 Hugging Face 上的开源模型跑在本地,但需要一台显存足够的机器。毕设答辩现场网络状况不可控,我强烈建议准备两套配置:线上 API 优先,本地模型作为演示故障时的兜底。
3. 核心功能模块和数据链路拆解
3.1 系统功能全景
一个合格的股票行情预测与量化交易分析系统,至少应该包含六个模块。我按用户视角排序:
- 用户注册登录:基于 Django 自带认证体系扩展,支持 JWT 或 Session 登录。可在此处做角色区分,比如普通用户和管理员。
- 行情浏览模块:展示股票列表、K 线图、技术指标。支持按股票代码、名称搜索,支持日线、周线切换。
- 数据管理模块:数据采集入库、数据更新、数据清洗日志。这些信息对管理员可见,普通用户只看到清洗后的结果。
- 预测分析模块:对选中的股票展示模型预测结果,包括未来若干日预测价格或涨跌概率,附 LLM 生成的文字分析。
- 量化策略回测模块:选择策略(比如双均线、MACD、基于预测信号的择时策略),设置参数,运行回测,输出收益率曲线、回撤曲线和关键指标。
- 可视化大屏:一个聚合页面,展示市场整体情况、涨幅榜、情绪分布、模型预测分布。这就是热词里反复出现的“校园大数据—数据可视化”和“echarts数据可视化大屏”在股票场景下的一种迁移实现。
这个功能列表如果全部做完,论文素材已经非常充足了。如果时间紧,可以砍掉第 6 项的复杂度,保留基本图表即可。
3.2 行情数据的获取、清洗与存储
数据是整个系统的基础,这一块做不好,后面预测和回测都是空中楼阁。用 AKShare 获取 A 股日线数据,通常就几行代码:
import akshare as ak # 获取单只股票的日线行情,比如贵州茅台 df = ak.stock_zh_a_hist(symbol="600519", period="daily", start_date="20150101", end_date="20250501", adjust="qfq") # 列名通常是:日期、开盘、收盘、最高、最低、成交量、成交额、振幅、涨跌幅、涨跌额、换手率 print(df.head())这里有一个非常重要的参数:adjust="qfq",前复权。为什么要复权?因为股票会发生分红送股,不复权的价格会出现人工跳空,导致均线、MACD 等指标计算失真,回测也会出现虚假收益。很多新手直接拿不复权数据做回测,结果发现茅台在 2017 年某天突然下跌 20%,百思不得其解,其实就是除权除息带来的缺口。
拿到数据之后的清洗流程建议做成一个独立函数,至少要做这几件事:
- 去重:按交易日期去重,防止接口重复抓取。
- 排序:按日期升序排列,确保后面计算指标时窗口顺序正确。
- 缺失值处理:停牌日是没有数据的,有两种做法:要么按前向填充(forward fill),要么直接删除当日记录。我建议删除,因为把停牌日填上数据会影响技术指标的真实性。
- 类型转换:日期转 datetime,成交量、成交额转数值类型。
- 涨跌停检查:如果某天出现超过 ±10% 的异常波动(新股上市首日除外),结合新闻数据判断是否异常,异常数据标记出来。
清洗完后存入 MySQL,表结构参考如下:
CREATE TABLE stock_daily ( id BIGINT AUTO_INCREMENT PRIMARY KEY, symbol VARCHAR(10) NOT NULL, trade_date DATE NOT NULL, open_price FLOAT, close_price FLOAT, high_price FLOAT, low_price FLOAT, volume BIGINT, amount BIGINT, pct_chg FLOAT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_symbol_date (symbol, trade_date) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;给symbol + trade_date建唯一索引非常关键,这样你在做增量更新时可以用“先查询最大日期,再拉取新数据”的策略,避免全量重抓,速度提升明显。
3.3 特征工程:把原始行情变成模型能用的特征
拿到清洗后的行情数据,还不能直接喂给模型。我们要构造技术指标特征。常用的有:
- 移动平均线:MA5、MA10、MA20、MA60,反映不同周期的趋势。
- MACD:DIF、DEA 和柱状图,反映趋势和动能。
- RSI:相对强弱指标,衡量超买超卖状态。
- 布林带:中轨、上轨、下轨,用波动率判断支撑阻力。
- 成交量相关:成交量 5 日均值、量比、换手率。
用 pandas 计算这些指标非常方便:
import pandas as pd df["MA5"] = df["close_price"].rolling(window=5).mean() df["MA20"] = df["close_price"].rolling(window=20).mean() df["RSI14"] = compute_rsi(df["close_price"], 14) df["DIF"], df["DEA"], df["MACD"] = compute_macd(df["close_price"]) df["volume_ma5"] = df["volume"].rolling(window=5).mean() df["label"] = (df["close_price"].shift(-5) > df["close_price"]).astype(int)这里有个核心问题:预测目标是什么?我强烈建议不要直接“预测明天的收盘价是多少”,因为价格回归的误差在答辩时很难解释清楚,精确值预测在金融里本来就是个伪命题。更合理的做法是预测未来 5 日涨跌方向,也就是上面代码里的label:未来第 5 天的收盘价高于今天,记为 1,否则为 0。这本质上是一个二分类问题,评估时用准确率、精确率、召回率、F1 都容易解释,也符合量化里最常见的“择时”应用场景。
在构建特征时一定要警惕一个隐蔽的错误:使用未来数据。比如你想用明天的成交量作为今天的特征,这在回测里是未来函数,会让模型表现虚高。凡是shift(-n)的数据只能用于构造标签,不能用于特征;特征只能使用shift(n)的历史数据。这是论文里值得写一段的重点。
3.4 预测模型:LSTM/GBDT 为主,LLM 为辅
有了特征和标签,接下来选模型。在毕设语境下,我的推荐梯队是这样的:
- 首选:LightGBM 或 XGBoost。表格数据上的表现稳定、训练快、调参简单,几千行数据就能训练出像样的结果。答辩时解释树模型的可解释性也容易。
- 备选:LSTM。如果导师明确要求“深度学习”,就用 LSTM。但 LSTM 在小样本金融数据上很容易过拟合,需要做早停、正则化。
- 不建议:Transformer 自己从头训。没有大量数据和算力,自己训的 Transformer 效果大概率不如 LightGBM,还容易被认为是“套壳”。
这个题目的巧妙之处在于,LLM 不参与直接数值预测,而是负责生成情绪因子和解释文本。你可以把新闻情绪分数作为一个特征列,和 MA、RSI 一起喂给 LightGBM。论文里就可以理直气壮地写:“传统因子反映量价关系,LLM 情绪因子反映市场预期,两者互补。”
LLM 情绪分析的实现也不复杂,核心是把新闻标题或正文发给模型,让它返回结构化 JSON:
prompt = """ 你是一个金融分析师。请分析下面这条新闻对某个股票的情绪影响。 返回 JSON 格式:{"sentiment": "positive/neutral/negative", "score": 0到1之间的数值} 新闻内容:{} """.format(news_text)拿到 score 之后,按股票按天聚合,得到“当日情绪均值”,再和历史行情数据 join,形成一个完整的数据集。整套链路是清晰且可复现的。
4. 量化交易策略与回测:让预测落地成结果
4.1 从预测信号到交易策略的桥梁
预测模型输出的是“未来 5 日上涨概率”,但概率本身不能直接当策略。你需要定义一条规则把概率转化为买卖动作。这里推荐做一个简单的阈值策略:
- 当预测上涨概率 ≥ 0.6 时,生成买入信号。
- 当预测上涨概率 ≤ 0.4 时,生成卖出或清仓信号。
- 介于 0.4 和 0.6 之间时,保持仓位不变。
这种基于预测信号的择时策略,在论文里可以解释为“模型驱动决策”,逻辑顺畅,代码也不复杂。但仅做这一个策略,内容略显单薄,建议再加两个经典技术策略做对照:
- 双均线策略:MA5 上穿 MA20 买入,下穿卖出。这是趋势跟随策略,代码几行就能实现,答辩时可解释性强。
- MACD 金叉死叉策略:DIF 上穿 DEA 买入,下穿卖出,结合柱状图判断。
你有三个策略,就可以在论文里做“策略绩效对比”,加上基准(比如买入持有指数),形成一组非常漂亮的对比实验图表。这部分是论文里最容易出彩、也最容易拿高分的内容。
4.2 回测引擎:自己写还是用库
回测有两种路线:自己写一个轻量回测引擎,或者用 backtrader 这类现成框架。我个人建议自己写,原因有三个:
- 毕设场景下,只需支持日线、单股票、单策略,自己写几百行就够;
- 可控性更强,回测过程一目了然,答辩时被问“你的回测逻辑是什么”可以答得滴水不漏;
- 使用现成框架,如果配置不熟反而浪费时间,而且代码量显得不足。
一个简要的回测逻辑如下:
def run_backtest(df, buy_signal, sell_signal, initial_cash=100000): cash = initial_cash shares = 0 equity_curve = [] for i in range(len(df)): if buy_signal[i] and shares == 0: shares = int(cash / df["close_price"][i] / 100) * 100 cash -= shares * df["close_price"][i] elif sell_signal[i] and shares > 0: cash += shares * df["close_price"][i] shares = 0 equity = cash + shares * df["close_price"][i] equity_curve.append(equity) return equity_curve这里有一个 A 股特有的细节:交易单位是手,一手是 100 股,所以买入时要对 100 取整。我见过很多人在回测里忽略这一点,导致回测收益率虚高,答辩时被老师用常识一问就露馅。另外一个细节是手续费和印花税,虽然 A 股印花税在 2023 年后有过调整,但回测里至少要加上万分之一到千分之一量级的交易成本,这样算出来的收益曲线才可信。
4.3 回测指标:夏普比率、最大回撤怎么算
论文里一定要有量化指标,不能只贴一张收益曲线图。至少要包含以下四个:
| 指标 | 含义 | 计算公式简化版 |
|---|---|---|
| 年化收益率 | 策略一年的平均收益水平 | 资金终值 / 本金^(252/交易天数) - 1 |
| 最大回撤 | 从峰值跌下来的最大幅度 | max(峰值 - 谷值) / 峰值 |
| 夏普比率 | 单位风险获得的超额收益 | (策略年化收益 - 无风险利率) / 收益波动率 |
| 胜率 | 单次交易赚钱的比例 | 盈利交易次数 / 总交易次数 |
最大回撤尤其要重视,因为它是衡量策略风险最直白的指标。如果你做出的策略年化收益 80%、最大回撤 30%,答辩时被问“这个波动你能接受吗”,你要能解释回撤发生的原因。计算最大回撤的代码很简单:
import numpy as np equity = np.array(equity_curve) rolling_max = np.maximum.accumulate(equity) drawdown = (equity - rolling_max) / rolling_max max_drawdown = drawdown.min()夏普比率在论文里解释为“每承受一单位波动,能换来多少超额回报”,对金融背景不深的人也很好理解。这里要注意,计算夏普比率时用“日收益率的标准差再乘以根号 252”年化,这是行业通用做法,公式写进论文会有专业感。
4.4 过拟合问题:回测好不等于实盘好
这是整个项目里最需要向导师讲清楚的一点。很多新手做回测,调参调到收益曲线完美向上,觉得自己发现了印钞机,其实已经严重过拟合。
我在实际操作中常用的检验方法是样本外测试:把数据按时间切分成训练段(比如 2018-2022)和测试段(2023 之后),训练模型只用训练段,测试段只用来评估。如果模型在训练段表现很好、测试段大幅变差,说明过拟合;如果两段表现接近,说明策略有一定泛化能力。
另一个技巧是参数敏感性分析:把策略参数(比如均线周期 5/10/20)稍微扰动一下,看看策略表现是不是剧烈变化。如果参数从 5 改成 7 就从盈利变亏损,说明策略脆得像纸,论文里应该如实讨论这一点。把“回测的局限性与未来改进方向”写成论文的一个小节,反而是加分项。
5. 开发实战:从空文件夹到跑通全流程
5.1 项目骨架与初始化
使用常规的 Django 开发流程,在虚拟环境下初始化项目:
pip install django celery redis mysqlclient akshare pandas scikit-learn lightgbm django-admin startproject stock_project . python manage.py startapp users python manage.py startapp analysis在settings.py里配置 MySQL 数据库:
DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "stock_db", "USER": "root", "PASSWORD": "your_password", "HOST": "127.0.0.1", "PORT": "3306", "OPTIONS": {"charset": "utf8mb4"}, } }很多新手在用 Django 连接 MySQL 时会在django/contrib/admin自带的几个表迁移时报错,尤其是字符集问题。解决方案就是上面OPTIONS里指定utf8mb4,同时确保 MySQL 数据库本身也是utf8mb4字符集,否则中文新闻数据存进去容易报错或者乱码。
5.2 异步任务:回测不能卡死页面
这个项目有个非常现实的工程问题:回测一个五年周期的双均线策略,虽然计算量不大,但如果同时加上数据清洗和特征计算,同步执行会让页面卡住十几秒甚至更久。毕业论文做功能演示时,如果点一个按钮页面白屏十秒,现场效果很尴尬。
解决方案是使用Celery 异步任务队列。用户在网页上点击“运行回测”,Django view 把任务丢给 Celery,立刻返回“任务已提交”,前端通过轮询或者 WebSocket 查询任务状态,任务完成后展示结果。
Celery 配置非常常规:
# settings.py CELERY_BROKER_URL = "redis://localhost:6379/0" CELERY_RESULT_BACKEND = "redis://localhost:6379/1"在 app 里定义异步任务:
from celery import shared_task @shared_task def run_backtest_task(symbol, strategy_name, params): # 这里执行完整的回测逻辑 result = execute_backtest(symbol, strategy_name, params) return resultDjango 视图里只需这样调用:
task = run_backtest_task.delay(symbol, strategy_name, params) # task.id 返回给前端,前端用 task.id 查询状态热词里多次出现“django python websocket实现后台有数据前端推送”,这确实是个实用方向。如果不想引入 Django Channels(它配置相对繁琐),可以用一个更轻量的方案:前端每隔两三秒轮询一次TaskResult接口,实现“有数据前端推送”的效果已经足够。论文里写“基于轮询的任务状态同步机制”也说得通。
5.3 前端可视化:ECharts 的正确用法
ECharts 在毕设里是可视化神器。股票 K 线图是最典型的需求,ECharts 的candlestick系列可以直接用:
option = { xAxis: { type: "category", data: dates }, yAxis: { scale: true }, series: [{ type: "candlestick", data: klineData // 每项是 [open, close, lowest, highest] }] };这里要注意一个非常容易搞错的点:ECharts 的 K 线数据顺序是 [开盘, 收盘, 最低, 最高],不是 [开盘, 最高, 最低, 收盘]。我见过太多人因为顺序反了画出来的 K 线阴阳颠倒。在后端返回 JSON 时,就要把顺序整好:
# 后端序列化 kline_data = [ { "date": row["trade_date"], "ohlc": [row["open_price"], row["close_price"], row["low_price"], row["high_price"]], } for row in rows ]前端在图上方叠加 MA5、MA20 折线,再加成交量柱状图,配一个数据范围选择器(dataZoom),视觉效果就非常完整了。
另外一个新手集中翻车的点,就是热词里的“vscode写img标签在django的static文件中显示不了”。Django 的静态文件机制跟普通 HTML 完全不一样,必须在设置里配置:
STATIC_URL = "/static/" STATICFILES_DIRS = [ BASE_DIR / "static", ]然后在模板里使用:
{% load static %} <img src="{% static 'img/logo.png' %}" alt="logo">直接写<img src="/static/img/logo.png">在开发环境下通常也能访问,但模板里用{% static %}才是标准做法,部署时配合collectstatic才不会出错。
5.4 训练与预测模块的实现要点
模型训练部分我建议做成一个独立的命令行脚本,而不是每次从 Web 页面触发,因为训练过程需要观察日志和调参。脚本的逻辑大致是:
- 从 MySQL 读取某只股票的清洗后行情数据。
- 计算技术指标特征,合并 LLM 情绪因子。
- 按时间切分训练集和测试集。
- 训练 LightGBM 分类器。
- 保存模型文件(
model.pkl),记录特征列表和模型评估指标。 - 将评估指标存入数据库,供 Web 端展示。
在 Web 端,预测接口的职责只是“读取已经训练好的模型,加载最新数据,计算特征,调用model.predict_proba输出概率”,再把概率传递给 LLM 生成文字解读。这种“离线训练、在线预测”的架构在论文里可以写得很专业,而且工程上非常稳健,不会让 Web 服务器承担训练时的内存压力。
5.5 部署与演示环境
毕设答辩的环境千变万化,最稳妥的方案是把项目打包成 Docker Compose 一键启动。一个docker-compose.yml把 MySQL、Redis、Django 应用、Celery worker 全部编排起来,答辩前在演示机器上docker compose up -d就能跑起来,不用现场装依赖。
如果对方机器不好使,另一个备选方案是准备好一个已经配置好的虚拟机镜像,或者用云服务器把系统放上去,演示时直接用浏览器访问公网地址。多重保障一定比单一方案稳。我遇到过最惨的情况是答辩前一天电脑系统崩了,还好有一份云服务器版本,否则当场傻眼。
6. 常见问题与避坑清单
整理一下我在实操中真正遇到过的问题,既有数据层面的、也有工程层面的、还有模型层面的,按优先级列出来:
6.1 数据类问题
- 除权除息导致的假跳空:不复权数据会让均线、MACD 出现失真。解决方案是使用前复权数据,并在论文数据预处理环节写明“采用前复权价格”。
- 停牌日缺失:直接用
resample填充会造成虚假交易记录,最好删除,但要注意指标计算的窗口连续性。 - 接口数据字段变化:AKShare 的字段名会随版本升级变化,建议在代码里加一层
rename映射,不要直接硬编码。 - 时区问题:MySQL 默认时区可能与 Django 的
USE_TZ设置不一致,导致日期偏移一天。建议USE_TZ = True,数据库连接加CONN_MAX_AGE,同时所有时间字段都用 UTC 存储,展示时再转本地时间。
6.2 Django 工程类问题
- 静态文件 404:开发时
STATICFILES_DIRS配置错误,或者图片路径大小写不匹配;部署时忘记python manage.py collectstatic。 - 跨域问题:如果前端单独运行(比如 Vue 开发服务器),需要安装
django-cors-headers并配置白名单。 - 数据库迁移冲突:多人协作或者多次改动模型后,
makemigrations可能产生脏迁移。建议每次修改模型后立即生成迁移文件,不要攒到最后。 - Celery 任务重复执行:使用 Redis 作为 broker 时,如果任务有幂等性要求,需要自己做幂等控制,否则回调重试会重复写入回测结果。
6.3 模型类问题
- 标签泄露:用未来数据构建特征,回测结果虚高。这是最严重的建模错误,论文里应对此做专门的“避免未来函数”说明。
- 类别不平衡:A 股上涨和下跌的天数基本接近,但如果用未来 5 日涨跌作为标签,会出现类别不均衡。可以用
class_weight或者在评估时关注 AUC 而非准确率。 - LLM 输出不稳定:大模型生成的 JSON 偶尔不符合格式,建议在请求里指定输出 schema,并做解析异常兜底,解析失败时默认情绪分数为 0。
6.4 答辩现场问题
- 网络突然断了怎么办:本地要有一份缓存数据和离线版本的大模型方案。答辩演示前把常用股票的数据跑一遍,让页面打开就有数据展示,不要现场从零拉取接口。
- 模型训练时间太长怎么办:Web 端不要触发训练,只用预训练结果。
- 老师问“这个能实盘吗”怎么回答:老老实实说“实盘需要考虑滑点、冲击成本、涨跌停限制、停牌、流动性等因素,本系统是教学和研究性质的回测验证,距离实盘还有很长的距离”,这种诚实反而比吹牛更容易得高分。
7. 论文、PPT 和答辩讲解怎么组织
7.1 论文结构参考
毕业设计的 LW(论文/文档)不需要太花哨,但结构必须完整。我建议按这个顺序写:
- 绪论:研究背景和意义,重点写“传统预测忽视文本信息,LLM 可以补足”。
- 相关技术介绍:Django、MySQL、机器学习、大模型、量化交易基础概念。这里可以把技术原理写透,是凑字数和展示理论水平的大好地方。
- 需求分析:功能需求、非功能需求(性能、可用性)、可行性分析。
- 系统设计:总体架构图、功能模块图、数据库表设计、关键流程时序。
- 系统实现:每个模块的实现细节,配关键代码片段和截图。
- 模型实验与回测分析:数据集描述、特征说明、模型对比、回测结果、过拟合讨论。
- 系统测试:功能测试用例表、性能测试结果。
- 总结与展望。
这里我想特别提醒:不要把代码全贴进去。论文里放关键代码片段就行,比如特征计算 20 行、回测核心逻辑 20 行、LLM 调用 15 行,其余以流程图和文字描述为主。
7.2 PPT 制作的“三条主线”思路
答辩 PPT 页数控制在 15-20 页,时间十分钟左右。我建议按三条主线组织:
第一条线讲问题:股票预测为什么难,传统系统缺什么。 第二条线讲方案:你的系统怎么解决,架构什么样,每个技术各自承担什么。 第三条线讲结果:展示系统截图、模型评估指标、回测结果曲线。
PPT 里最忌讳大段文字。每页只放一个核心结论,能用图就不要用表格,能用表格就不要用段落。回测曲线图、K 线系统截图、LLM 分析报告示例图这三张图放上去,说服力比几百字强得多。
7.3 答辩讲解的黄金八分钟
答辩讲解时间很短,一定要在开场两分钟内说清楚三件事:
- 我做的系统是什么:一句话讲清楚。
- 解决什么问题:传统预测的盲区。
- 有什么亮点:LLM 情绪因子融合。
我强烈建议准备一个“30 秒电梯版本”用来回答老师开场“介绍一下你的项目”:“我开发了一个基于 Django 的股票行情预测与量化回测系统,核心创新是把大模型对财经新闻的情绪分析结果作为因子接入预测模型,并用回测框架验证策略有效性。”够短、信息密、有创新点。
然后,在剩余时间重点展示系统演示,演示时先跑数据看 K 线,再展示模型预测结果和一个 LLM 分析报告,最后跑一遍回测出指标。全程不要提“这个项目很难、我做了很久”,尽量把所有对系统的疑问留在演示和问答环节里解决。
最后再说几句心里话
这个题目我一路看下来,最大的感受是:它的难点不在于某个单独的技术点,而在于如何把多个技术点有机串起来。我见过太多人把项目做成了“四张皮”——Django 是 Django,模型是模型,LLM 是强行加上去的聊天框,回测是拿网上代码抄的,答辩时一追问就露馅。这个项目的价值恰恰在于每个模块都服务于同一件事:让股票预测从“只看 K 线”变成“结合量价关系、技术指标和新闻情绪的综合判断”。所以我在实际操作中一直强调,论文的架构图要画在写代码之前,核心链路的每一步都要能讲出“为什么”,这比多写两万行代码更重要。
如果你正在做这个方向,最后再分享一个亲测好用的建议:把 LLM 分析报告的展示做成纯文本截图之后立刻存下来。答辩现场演示大模型生成报告,万一网络抖动或者生成时间太长,你至少可以把这张图切进 PPT 里兜底。系统可以做到 90 分完美,但答辩演示必须要做到 100 分稳定——这几乎是所有能拿优秀毕设的项目的共性。祝答辩顺利。