ChatGPT分析股票靠谱吗?探索人工智能在股票收益预测中的过拟合和错误
引言
生成式人工智能(Generative AI)在交通、医疗和经济学等多个领域展示了巨大的潜力。除了自动驾驶汽车和改进的疾病检测之外,AI还可能通过客观分析大量信息来彻底改变金融决策。例如,最近的技术进步已被证明可以提高个人投资者、卖方分析师和公司审计员的绩效。
然而,LLM和其他AI算法通常以人类输出为训练数据,研究表明这些方法可能会嵌入有害的社会偏见。如果AI算法模仿人类决策,它们也可能包含个人在金融环境中表现出的认知偏差。大量文献记录了人们过度外推近期表现、倾向于过度乐观,以及对自己的预测过于自信等行为。
本文研究了大型语言模型(Large Language Models,LLMs)如何解读历史股票收益,并将其预测与来自众包平台的股票排名估计进行比较。尽管股票收益呈现短期反转,LLM的预测却过度外推,对近期表现赋予过高的权重,类似于人类的行为。LLM的预测相对于历史和未来的实际收益表现出乐观倾向。当被提示提供80%置信区间的预测时,LLM的反应比调查结果更好地校准,但对异常值持悲观态度,导致预测分布偏斜。研究结果表明,LLM在预测预期收益时表现出常见的行为偏差,但在衡量风险方面比人类更出色。
关键词:大型语言模型、生成式AI、收益预测、外推预期、行为偏差
数据收集:投资者和LLM的股票收益预测
1. Forcerank平台的数据
我们的第一个人类预测数据来源是Forcerank,这是一个由Estimize运营的股票排名众包平台。Forcerank组织每周的比赛,参与者根据他们对下周股票表现的预测,对十只股票进行排名。参与者的目标是根据下周的实际收益,将十只股票从一到十进行排名。排名越高,得分越高。Forcerank根据参与者排名的准确性分配积分,并维护每周的排行榜。
我们的样本包含1,283个每周比赛,包括200只独特的股票代码。我们将每个比赛中股票的平均得分,作为投资者对股票在下周收益的共识预期。为了确保共识预期是基于参与者在提交排名之前已经观察到的股票收益,我们只考虑在第周结束时已知的收益。
数据处理代码示例
备注:完整代码论文复现请加入知识星球获取。
import pandas as pd
# 读取Forcerank数据
forcerank_data = pd.read_csv('forcerank_data.csv')
# 计算每个股票的平均得分
average_scores = forcerank_data.groupby(['contest_id', 'stock_id'])['score'].mean().reset_index()
# 提取需要的字段
average_scores = average_scores[['contest_id', 'stock_id', 'average_score']]
2. LLM预测的生成
我们的目标是将LLM的预测与人类提交的排名进行比较。我们为每个比赛创建一个包含十只股票过去十二周收益的数据文件,并向ChatGPT-4提供以下提示:
备注:完整代码论文复现请加入知识星球获取。
以下是十只股票从第t-12周到第t-1周的收益数据:
[插入数据表]
基于这些信息,请对这十只股票在第t周的收益进行排名。你对这个排名有多大的信心?
你的输出将采用JSON格式,格式如下:
'{"rank":{"1":"股票ID","2":"股票ID",...,"10":"股票ID"}, "confidence": }'。1代表最高收益,10代表最低收益。信心表示一个介于0到1之间的概率。
为了避免LLM可能的前瞻性偏差(look-ahead bias),我们在提示中只提供数值数据,而不包含任何公司的识别信息。
调用LLM生成预测的代码
备注:完整代码论文复现请加入知识星球获取。
import openai
import json
# 设置OpenAI API密钥
openai.api_key = 'your-api-key'
def get_gpt_prediction(return_data):
prompt = f"""
以下是十只股票从第t-12周到第t-1周的收益数据:
{return_data}
基于这些信息,请对这十只股票在第t周的收益进行排名。你对这个排名有多大的信心?
你的输出将采用JSON格式,格式如下:
'{{"rank":{{"1":"股票ID","2":"股票ID",...,"10":"股票ID"}}, "confidence": }}'。1代表最高收益,10代表最低收益。信心表示一个介于0到1之间的概率。
"""
......
)
return prediction
# 示例调用
# return_data应为格式化的收益数据字符串
prediction = get_gpt_prediction(return_data)
3. 市场情绪预测
我们还收集了美国个人投资者协会(American Association of Individual Investors, AAII)的情绪调查数据,用于衡量人类对整体市场表现的预期。AAII调查每周收集会员对未来六个月市场走势的看法:看涨、中性或看跌。
为了获取LLM的市场情绪预测,我们向ChatGPT提供标普500指数过去12个月的月度收益数据,并提示其回答以下问题:
CSV数据包含从第t-12个月到第t-1个月的月度股票收益。
请回答以下问题:
你认为未来六个月股票市场的走势会是上涨(看涨)、不变(中性)还是下跌(看跌)?
你对这个预测有多大的信心?
你的输出将采用JSON格式,格式如下:
'{"prediction":,"confidence":}'。1代表看涨,0代表中性,-1代表看跌。信心表示一个介于0到1之间的概率。
获取市场情绪预测的代码
备注:完整代码论文复现请加入知识星球获取。
def get_market_sentiment(sp500_returns):
prompt = f"""
CSV数据包含从第t-12个月到第t-1个月的月度股票收益:
{sp500_returns}
请回答以下问题:
你认为未来六个月股票市场的走势会是上涨(看涨)、不变(中性)还是下跌(看跌)?
你对这个预测有多大的信心?
你的输出将采用JSON格式,格式如下:
'{{"prediction":,"confidence":}}'。1代表看涨,0代表中性,-1代表看跌。信心表示一个介于0到1之间的概率。
"""
response = openai.Completion.create(
engine='text-davinci-003',
prompt=prompt,
max_tokens=150,
temperature=0
)
sentiment = json.loads(response.choices[0].text.strip())
return sentiment
# 示例调用
# sp500_returns应为格式化的标普500指数收益数据字符串
sentiment_prediction = get_market_sentiment(sp500_returns)
LLM的预期形成机制
历史收益的时间影响——外推
我们首先研究历史收益的时间对人类和LLM预测的影响,以及与实际收益的关系。采用以下回归模型:
其中:
- ? :股票在第周的人类Forcerank得分、ChatGPT-4预测排名或第周的实际收益表现。
- ? :股票在第周的收益(滞后收益)。
结果分析
- 1. 人类预测:回归结果显示,人类的预测对过去收益有显著的正向依赖。所有滞后收益的系数均为正值,且近期收益的系数更大,表明人们对近期收益赋予了更高的权重。
- 2. LLM预测:ChatGPT-4的预测排名显示出更强的对近期收益的依赖性。特别是,对上一周收益的系数远高于之前几周的收益系数。这种对近期收益的过度依赖与人类的行为偏差相似。
- 3. 实际收益:与人类和LLM的预期相反,实际的股票收益呈现出短期反转(short-term reversal)的特征。回归结果显示,近期滞后收益的系数为负值,表明近期收益较高的股票在下周可能表现较差。
回归分析代码
备注:完整代码论文复现请加入知识星球获取。
import statsmodels.api as sm
# 合并人类预测、LLM预测和实际收益数据
data = pd.merge(average_scores, gpt_predictions, on=['contest_id', 'stock_id'])
data = pd.merge(data, stock_returns, on=['contest_id', 'stock_id'])
# 准备滞后收益数据
for lag in range(1, 13):
data[f'return_lag_{lag}'] = data.groupby('stock_id')['return'].shift(lag)
# 回归模型
X = data[[f'return_lag_{lag}' for lag in range(1, 13)]]
X = sm.add_constant(X)
# 人类预测回归
......
# LLM预测回归
......
# 实际收益回归
y_actual = data['return']
model_actual = sm.OLS(y_actual, X, missing='drop').fit()
print(model_actual.summary())
外推模型的参数估计
为了更简洁地捕捉滞后收益系数随时间的衰减模式,我们估计了一个假设收益权重呈指数衰减的参数化模型:
其中,权重定义为:
参数解释:
- ? (水平系数):捕捉投资者预期对过去收益的整体响应程度。越大,表明对过去收益的敏感度越高。
- ? (斜率系数):决定过去收益在形成预期时的相对权重。越小,表明对近期收益赋予更高的权重,体现出更强的外推倾向。
参数估计代码
备注:完整代码论文复现请加入知识星球获取。
from scipy.optimize import minimize
import numpy as np
def exponential_decay_model(params, returns, Y):
lambda1, lambda2 = params
n = len(returns.columns)
weights = np.array([lambda2**s for s in range(n)])
weights = weights / weights.sum()
pred = 5.5 + lambda1 * (returns.values * weights).sum(axis=1)
error = Y - pred
return (error**2).mean()
# 准备数据
returns_lagged = data[[f'return_lag_{lag}' for lag in range(1, 13)]].dropna()
Y_human = data['average_score'].loc[returns_lagged.index]
# 初始参数
initial_params = [1.0, 0.9]
# 优化
result = minimize(exponential_decay_model, initial_params, args=(returns_lagged, Y_human))
lambda1_opt, lambda2_opt = result.x
print(f"Optimal lambda1: {lambda1_opt}")
print(f"Optimal lambda2: {lambda2_opt}")
行为偏差的进一步分析
我们还探讨了LLM对正负收益的反应是否与人类不同。将滞后收益分解为正负部分:
其中:
- ? :当时取该值,否则为0。
- ? :当时取该值,否则为0。
正负收益回归代码
备注:完整代码论文复现请加入知识星球获取。
# 创建正负收益
for lag in range(1, 13):
data[f'return_lag_{lag}_pos'] = data[f'return_lag_{lag}'].apply(lambda x: x if x > 0 else 0)
data[f'return_lag_{lag}_neg'] = data[f'return_lag_{lag}'].apply(lambda x: x if x < 0 else 0)
# 准备回归变量
X_pos = data[[f'return_lag_{lag}_pos' for lag in range(1, 13)]]
X_neg = data[[f'return_lag_{lag}_neg' for lag in range(1, 13)]]
X = pd.concat([X_pos, X_neg], axis=1)
X = sm.add_constant(X)
# 人类预测回归
......
# LLM预测回归
model_gpt_pos_neg = sm.OLS(y_gpt, X, missing='drop').fit()
print(model_gpt_pos_neg.summary())
图像数据的影响
为了研究LLM如何处理视觉金融数据,我们还向ChatGPT提供了十只股票的蜡烛图(展示过去12或24周的价格走势)。结果显示,即使在提供图像数据的情况下,LLM仍然对近期收益表现出过度外推的倾向。
处理图像数据的代码
备注:完整代码论文复现请加入知识星球获取。
由于无法直接展示,我们假设有函数可以生成并提供图像数据给LLM:
def get_gpt_prediction_from_images(image_paths):
# 由于API限制,无法直接传递图像,因此这里只是示意
prompt = f"""
以下是十只股票过去12周的每日价格蜡烛图。
[插入图像路径或描述]
基于这些信息,请对这十只股票在下周的收益进行排名。
你的输出将采用JSON格式,格式如下:
'{{"rank":{{"1":"股票ID","2":"股票ID",...,"10":"股票ID"}}}}'。1代表最高收益,10代表最低收益。
"""
# 调用LLM接口
# ...
# 示例调用
image_paths = ['image1.png', 'image2.png', ..., 'image10.png']
prediction_from_images = get_gpt_prediction_from_images(image_paths)
对未来收益的预测能力
尽管LLM的预测在某种程度上反映了人类的行为偏差,但其对未来收益的预测能力如何?通过Fama-MacBeth回归,我们发现:
- ? LLM预测与未来一周的收益呈负相关,尤其是预测中外推成分更显著地预测了未来的负收益。这与实际市场中短期反转的特征一致。
Fama-MacBeth回归代码
备注:完整代码论文复现请加入知识星球获取。
import statsmodels.formula.api as smf
# 添加控制变量
data['size'] = data['market_cap'].apply(np.log)
data['bm'] = data['book_to_market']
# ...其他控制变量
# 构建截面回归公式
......
# 按时间循环进行回归
for date in dates:
.......
# 计算平均系数和t统计量
coefficients_df = pd.DataFrame(coefficients)
mean_coefficients = coefficients_df.mean()
t_values = mean_coefficients / (coefficients_df.std() / np.sqrt(len(dates)))
print(mean_coefficients)
print(t_values)
市场情绪分析
我们将LLM的市场情绪预测与AAII的调查结果进行了比较,采用模型:
结果显示:
- ? LLM情绪与人类情绪一致,对近期市场收益赋予了更大的正权重,表现出外推的行为。
- ? 使用其他LLM(如Claude)进行验证,结果相似,表明这种行为并非ChatGPT特有。
市场情绪回归代码
备注:论文PDF和完整代码复现请加入知识星球获取。
# 准备AAII情绪数据和LLM情绪数据
aaii_data = pd.read_csv('aaii_sentiment.csv')
gpt_sentiment = pd.read_csv('gpt_sentiment.csv')
# 合并数据
sentiment_data = pd.merge(aaii_data, gpt_sentiment, on='date')
sentiment_data['sp500_return'] = sentiment_data['sp500_return'].astype(float)
# 准备滞后收益
......
# 回归模型
......
# AAII情绪回归
......
# LLM情绪回归
y_gpt_sentiment = sentiment_data['gpt_sentiment']
model_gpt_sentiment = sm.OLS(y_gpt_sentiment, X, missing='drop').fit()
print(model_gpt_sentiment.summary())
历史收益幅度的影响——偏差和误判
为了深入研究LLM如何处理历史收益的幅度信息,我们随机选取了10,000个股票-月份的观测值。对于每个观测值,我们收集了最长10年的历史月度收益数据,并向ChatGPT-4提出以下问题,类似于**Ben-David, Graham和Harvey(2013)**对CFO的调查:
以下是某金融资产过去120个月的月度收益。
请回答以下关于下个月收益的问题:
有10%的可能性实际收益低于a%。
我预计下个月的收益为b%。
有10%的可能性实际收益高于c%。
请以JSON格式返回:
'{"low": a%, "expected": b%, "high": c%}'。
结果分析
- 1. 预期收益的偏差:
- ? ChatGPT的预期收益平均值为2.2%,显著高于提供给它的历史收益平均值(1.4%)和下个月的实际收益(1.1%)。
- ? 这表明LLM的预测存在过度乐观的倾向。
- 2. 置信区间的校准:
- ? ChatGPT预测的80%置信区间包含实际收益的76.9%,略低于使用历史10%和90%百分位数(79.0%)。
- ? 与CFO调查中严重的误判(实际收益仅有36%落在他们的80%置信区间内)相比,LLM的校准明显更好。
- 3. 预测分布的偏斜:
- ? ChatGPT的低端预测(Low)低于历史10%百分位数,高端预测(High)也低于历史90%百分位数。
- ? 这表明LLM对极端值持保守态度,导致预测分布的正偏斜。
数据处理和分析代码
备注:完整代码论文复现请加入知识星球获取。
# 读取历史月度收益数据
monthly_returns = pd.read_csv('monthly_returns.csv')
# 计算历史统计量
monthly_returns['mean'] = monthly_returns.mean(axis=1)
monthly_returns['std'] = monthly_returns.std(axis=1)
monthly_returns['percentile_10'] = monthly_returns.quantile(0.10, axis=1)
monthly_returns['percentile_90'] = monthly_returns.quantile(0.90, axis=1)
# 调用ChatGPT获取预测
def get_gpt_forecast(historical_returns):
prompt = f"""
以下是某金融资产过去120个月的月度收益。
{historical_returns}
请回答以下关于下个月收益的问题:
有10%的可能性实际收益低于a%。
我预计下个月的收益为b%。
有10%的可能性实际收益高于c%。
请以JSON格式返回:
'{{"low": a%, "expected": b%, "high": c%}}'。
"""
response = openai.Completion.create(
engine='text-davinci-003',
prompt=prompt,
max_tokens=150,
temperature=0
)
forecast = json.loads(response.choices[0].text.strip())
return forecast
# 获取预测并比较
......
# 将预测结果与实际值进行比较
......
# 计算预测偏差和校准
......
# 统计分析
......
进一步的回归分析
为了更深入地了解LLM如何将历史收益分布转化为预测,我们对ChatGPT-4的预测进行了回归分析:
其中:
- ? :ChatGPT-4对股票在第月的预测值,可以是Low、Expected或High。
- ? :股票历史收益的第百分位数。
回归分析代码
备注:完整代码论文复现请加入知识星球获取。
# 准备回归变量
regression_data = comparison[['expected', 'percentile_10', 'percentile_20', 'percentile_30',
'percentile_40', 'percentile_50', 'percentile_60', 'percentile_70',
'percentile_80', 'percentile_90']]
# 添加常数项
X = sm.add_constant(regression_data.drop(columns=['expected']))
y = regression_data['expected']
# 回归模型
model = sm.OLS(y, X).fit()
print(model.summary())
讨论
我们的研究表明,LLM在股票收益预测中表现出与人类相似的行为偏差,包括:
- ? 过度外推:对近期收益赋予过高的权重,忽视了实际收益中的短期反转特征。
- ? 乐观偏差:预期收益高于历史平均和实际收益,表现出过度乐观的倾向。
- ? 风险误判:尽管LLM在置信区间的校准上优于人类,但对极端值的预测较为保守,导致预测分布偏斜。
为什么难以消除LLM的偏差?
尽管LLM可以理论上“理解”这些行为偏差,但这些偏差深深嵌入在其训练数据中,因为训练数据反映了人类的思维方式,包括各种偏见和启发式。因此,完全消除这些偏差具有挑战性。
此外,LLM的训练过程涉及海量的数据,试图在不影响模型整体性能的情况下去除所有偏差几乎是不可能的。
结论
大型语言模型在客观分析大量信息方面展示了巨大的潜力,有可能革新金融决策。然而,由于LLM的训练数据包含人类的输出,可能会引入有害的认知偏差。本研究探讨了ChatGPT-4在提供历史收益数据并提示股票收益预测时,是否表现出行为偏差。
研究结果表明:
- ? LLM的预测与人类相似,存在过度外推近期收益的行为。
- ? LLM对预期收益表现出过度乐观,但在风险评估上比人类更准确。
- ? 尽管LLM在某些方面优于人类,但在金融决策中仍需谨慎对待其预测,防止可能的偏差影响。
对未来的启示
- ? 审慎使用LLM预测:在使用LLM进行金融预测时,需要考虑其可能的行为偏差,避免过度依赖。
- ? 改进模型训练:未来的研究可以尝试通过调整训练数据或引入校正机制,减轻LLM的行为偏差。
- ? 人机协作:将LLM的优势与人类的判断相结合,可能会带来更好的决策结果。
希望本篇文章能为大家带来AI+Quant的启发,欢迎加入LLMQuant社区获得更加成熟交流和探讨!
论文PDF和完整代码复现请加入知识星球获取。以上示例 / 代码仅供学习和参考,实际应用中需考虑更多因素和细节。
本文基于论文《What Does ChatGPT Make of Historical Stock Returns? Extrapolation and Miscalibration in LLM Stock Return Forecasts》整理解读,旨在为读者提供对该研究的深入理解。如需进一步了解,请参阅原论文。