引言:LLM能预测股价吗?#
2025年以来,大语言模型(LLM)在金融领域的应用从”写研报”进化到了”做预测”。BloombergGPT、FinGPT、StockGPT等金融专用模型相继问世,但一个核心问题仍未解决:大模型到底能不能预测股价?
答案是:不能直接预测,但可以通过正确的训练范式,让LLM成为量化投资的”超级辅助”——从数据解读、因子发现到策略回测,LLM可以大幅提升研究效率。

本文将系统拆解训练一个”股市预测LLM”的完整链路——从金融数据预处理、指令微调,到RLHF对齐和实盘集成。
第一步:构建金融语料库#
为什么通用LLM不懂股票?#
通用LLM(如GPT-4、DeepSeek)的知识截止于训练数据,且缺乏对金融时间序列的结构化理解。要让LLM理解”MACD背离”、“波动率微笑”、“因子衰减”这些概念,需要专门的金融语料。
多模态金融数据集构建#
高质量的金融训练数据应包含三种模态:
1. 文本数据(~60%)
import json
from datasets import Dataset
# 构建金融文本语料
financial_text_corpus = {
"research_reports": [...], # 券商研报
"earnings_transcripts": [...], # 财报电话会议记录
"financial_news": [...], # 财经新闻
"regulatory_filings": [...], # 监管文件(年报、招股书)
"social_sentiment": [...] # 社交媒体情绪(雪球、推文)
}
# 组织为对话格式
def format_as_conversation(text_item):
return {
"messages": [
{"role": "system", "content": "你是一位资深量化分析师,擅长技术分析、基本面研究和宏观经济解读。"},
{"role": "user", "content": f"分析以下金融文本中的关键信息:\n{text_item['content']}"},
{"role": "assistant", "content": text_item['analysis']}
]
}python2. 时间序列数据(~30%)
import pandas as pd
import numpy as np
def build_time_series_corpus(symbols, start_date, end_date):
"""
构建股价时间序列语料,将原始OHLCV转换为文字描述
"""
descriptions = []
for symbol in symbols:
df = pd.read_csv(f"data/{symbol}.csv", parse_dates=['date'])
# 计算技术指标
df['ma_20'] = df['close'].rolling(20).mean()
df['ma_60'] = df['close'].rolling(60).mean()
df['rsi'] = compute_rsi(df['close'], 14)
df['volume_ratio'] = df['volume'] / df['volume'].rolling(20).mean()
# 生成自然语言描述
for idx, row in df.iterrows():
desc = f"""{row['date'].strftime('%Y年%m月%d日')},{symbol}:
收盘价 {row['close']:.2f}元,涨幅 {row['pct_change']:.2%}。
20日均线 {row['ma_20']:.2f},RSI(14) = {row['rsi']:.1f},
成交量较20日均量 {row['volume_ratio']:.0%}。"""
descriptions.append({
"symbol": symbol,
"date": row['date'],
"description": desc,
"next_day_return": df['pct_change'].shift(-1).iloc[idx]
})
return descriptionspython3. 结构化知识图谱(~10%)
将公司关系、产业链上下游、宏观指标关联等组织为知识图谱三元组,增强LLM的推理能力。
数据清洗的关键陷阱#
⚠️ 幸存者偏差:只使用现存股票的数据,会导致模型过度乐观 ⚠️ 前视偏差:确保训练集的标签(未来收益率)不会泄漏到输入特征中 ⚠️ 复权误差:分红送股后的前复权价格需要精确计算
第二步:预训练与领域适配#
Continue Pretraining策略#
不建议从零训练金融LLM(成本极高),而是对开源基座模型进行继续预训练(Continue Pretraining):
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers import TrainingArguments, Trainer
model_name = "deepseek-ai/deepseek-coder-7b-instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
# 配置训练参数
training_args = TrainingArguments(
output_dir="./fin-llm-checkpoints",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=8,
learning_rate=2e-5,
warmup_ratio=0.1,
logging_steps=50,
save_steps=500,
evaluation_strategy="steps",
eval_steps=500,
bf16=True, # 使用BF16加速
deepspeed="ds_config.json" # DeepSpeed ZeRO-3
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=financial_dataset,
eval_dataset=financial_eval_dataset,
)
trainer.train()python关键技术决策#
| 决策项 | 推荐方案 | 原因 |
|---|---|---|
| 基座模型 | 7B-13B参数 | 平衡推理成本和预测能力 |
| 预训练数据量 | 50-100B tokens | 充分学习金融领域知识 |
| 上下文长度 | 32K-128K | 覆盖长周期时间序列 |
| 训练策略 | LoRA + QLoRA | 显存友好,72B模型单卡可训 |
第三步:指令微调 —— 教模型”做预测”#
构建预测指令数据集#
指令微调(Instruction Tuning)是让LLM学会预测任务的关键步骤。需要构建三类指令:
# 1. 趋势预测类指令
trend_instructions = [
{
"instruction": "给定以下股票的技术指标,预测未来5个交易日的趋势方向(上涨/下跌/震荡)。",
"input": "股票:贵州茅台(600519)\n当前价格:1680.50\nMA20:1652.30\nRSI(14):58.2\nMACD:0.82(金叉信号)\n成交量:较前日增加35%",
"output": "预测:短期看涨\n理由:价格站上MA20,MACD金叉且成交量放大,RSI处于中性区间未超买,综合判断上涨概率65%。\n置信度:中\n风险提示:需关注大盘整体走势和白酒板块轮动。"
},
# ...更多样本
]
# 2. 风险预警类指令
risk_instructions = [
{
"instruction": "分析以下持仓组合的风险敞口,指出最大风险来源。",
"input": "组合:宁德时代(30%) + 茅台(25%) + 招商银行(20%) + 腾讯(25%)\n近期波动率:宁德42%、茅台28%、招行22%、腾讯35%",
"output": "最大风险敞口:宁德时代\n分析:宁德时代波动率最高(42%)且权重最大(30%),对组合波动的贡献度达38%。建议将宁德仓位降至20%以下,增加低波动品种对冲。"
}
]
# 3. 因子解释类指令
factor_instructions = [
{
"instruction": "用通俗语言解释'动量因子'在过去三个月的表现及其背后的市场逻辑。",
"input": "沪深300动量因子近3月收益:+2.3%,信息比率:0.45,最大回撤:-3.2%",
"output": "过去三个月动量因子表现中等偏上。市场呈现'强者恒强'特征:新能源、AI板块持续领涨,资金集中效应明显。但需注意因子拥挤度上升可能引发反转风险。"
}
]pythonSFT训练配置#
def prepare_sft_dataset(instructions):
"""将指令数据转换为SFT训练格式"""
dataset = []
for item in instructions:
# ChatML格式
prompt = f"""<|im_start|>system
你是一个训练有素的量化投资助手,基于金融数据做出审慎的投资分析和预测。
<|im_end|>
<|im_start|>user
{item['instruction']}
{item['input']}
<|im_end|>
<|im_start|>assistant
{item['output']}
<|im_end|>"""
dataset.append({"text": prompt})
return datasetpython第四步:RLHF对齐 —— 让预测更靠谱#
为什么需要RLHF?#
SFT后的模型会”说话”,但可能给出:过于自信的错误预测、忽略风险提示、无法量化不确定性。
**RLHF(人类反馈强化学习)**通过人类偏好反馈,让模型学会:
- 合理表达预测的不确定性
- 主动指出风险因素
- 避免给出过于具体的价格点位预测(合规考量)
奖励模型设计#
金融预测场景的奖励模型需考虑四个维度:
class FinancialPredictionRewardModel:
"""
金融预测场景的奖励模型
"""
def compute_reward(self, prediction, ground_truth, context):
reward = 0.0
# 1. 方向准确度(权重0.4)
if prediction['direction'] == ground_truth['direction']:
reward += 0.4 * (1.0 if prediction['confidence'] > 0.6 else 0.5)
# 2. 风险提示完整度(权重0.3)
risk_terms = ['风险', '回撤', '止损', '不确定性', '黑天鹅']
risk_coverage = sum(1 for t in risk_terms if t in prediction['text'])
reward += 0.3 * min(risk_coverage / 3, 1.0)
# 3. 不确定性量化(权重0.2)
if '概率' in prediction['text'] or '置信度' in prediction['text']:
reward += 0.2
# 4. 合规性惩罚(权重0.1)
forbidden_phrases = ['保证', '一定会上涨', '稳赚', '无风险']
for phrase in forbidden_phrases:
if phrase in prediction['text']:
reward -= 0.1
return max(reward, -1.0)pythonPPO训练流程#
from trl import PPOTrainer, PPOConfig, AutoModelForCausalLMWithValueHead
ppo_config = PPOConfig(
model_name="fin-llm-sft",
learning_rate=1.41e-5,
batch_size=16,
mini_batch_size=4,
ppo_epochs=4,
cliprange=0.2,
vf_coef=0.1,
ent_coef=0.01,
)
ppo_trainer = PPOTrainer(
config=ppo_config,
model=model,
ref_model=ref_model,
tokenizer=tokenizer,
dataset=fine_tuning_dataset,
)python第五步:评估与回测集成#
模型预测能力评估#
不能只看准确率,金融预测需要多维评估:
def evaluate_financial_llm(model, test_dataset):
"""
多维评估LLM的金融预测能力
"""
metrics = {
"direction_accuracy": [], # 方向准确率
"confidence_calibration": [], # 置信度校准
"risk_awareness_score": [], # 风险意识
"max_drawdown_simulation": [],# 模拟最大回撤
}
for sample in test_dataset:
prediction = model.generate(sample['prompt'])
# 方向准确率
if extract_direction(prediction) == sample['actual_direction']:
metrics["direction_accuracy"].append(1)
else:
metrics["direction_accuracy"].append(0)
# 置信度校准:预测置信度应与实际命中率匹配
predicted_conf = extract_confidence(prediction)
actual_hit = 1 if metrics["direction_accuracy"][-1] == 1 else 0
metrics["confidence_calibration"].append(abs(predicted_conf - actual_hit))
return {
"direction_acc": np.mean(metrics["direction_accuracy"]),
"calibration_error": np.mean(metrics["confidence_calibration"]),
}python实盘集成架构#
LLM不直接下单,而是作为信号生成器融入量化系统:
LLM预测信号 → 信号质量过滤 → 组合优化器 → 风控模块 → 执行引擎
↑ |
└──────────── 反馈循环(RL持续学习)←──────────┘plaintext
实战踩坑经验#
坑1:数据泄漏#
⚠️ 训练集和测试集按时间严格划分,不能用随机分割。某团队因混用不同年份数据导致回测夏普虚高1.2。
坑2:过度自信#
⚠️ LLM天生”自信”,即使不确定也会给出明确答案。必须通过RLHF强制要求输出置信度和风险提示。
坑3:市场结构变化#
⚠️ 2024年的市场规律与2021年完全不同。模型需要定期重新训练,建议每季度更新SFT数据。
坑4:合规红线#
⚠️ 在中国市场,给出具体股价预测目标位存在合规风险。建议将输出格式改为”概率区间”和”方向判断”。
总结#
训练一个股市预测LLM,本质上是让模型理解金融世界的”语言”和”逻辑”,而不是让它当”预言家”。
✅ 可行的方向:
- 用LLM做多源信息融合(财报+新闻+K线)
- 用LLM发现非结构化数据中的因子
- 用LLM生成策略回测代码
- 用LLM做投资组合风险解读
❌ 不可行的方向:
- 期望LLM准确预测具体股价
- 完全依赖LLM做自动化交易决策
- 不做回测就相信LLM的判断
“LLM不是水晶球,但它可以是你最聪明的量化研究员。”
关键词:大模型训练、股票预测、金融LLM、指令微调、RLHF、量化投资
参考资源:
- BloombergGPT: A Large Language Model for Finance (Wu et al., 2023)
- FinGPT: Open-Source Financial Large Language Models (Yang et al., 2023)
- DeepSeek-Coder: When the LLM Meets Finance (2025)