给程序员的投资指南——AI 在金融研究中的应用

111 阅读1小时+

本章涵盖的内容

  • 使用机器学习预测股价所面临的挑战
  • 用大语言模型开展投研
  • 通过 Python 向大语言模型提交提示词
  • 用提示工程改进提问质量

让我们用一个“激进”的想法开启本章:如果我们不再写代码做金融研究,而是把投资建议交给生成式 AI(GenAI)聊天机器人,会怎样?例如,我们可以问一个大语言模型(LLM):“我是风险厌恶型投资者,想投信息技术板块。请给出三只在回报最大化且风险最小化意义上更优的股票?”——你会在没有进一步尽调的情况下直接买入这三只股票吗?

本章前半部分将审视机器学习(ML)在金融中的判别式应用。我们会强调线性回归及类似算法在股价这类“混沌系统”中的局限:股价往往缺乏稳定模式,呈现“随机游走”。同时,我们也会说明这些算法在更可隔离的场景中如何发挥有意义的作用。

当本章后半部分引入 LLM 时,我们将强调:盲目照单全收 LLM 的投资建议是有风险的——因为它可能出现幻觉(hallucination),也可能信息过时。不过,我们会突出 GenAI 在金融研究中的价值,尤其是在你想更深入理解某家潜在投资标的公司时。简化来说,与其提出“给我推荐三只股票”这样泛化的问题,不如提交更具体的询问,比如:“请介绍 X 公司的管理层风格。”通过获取关于公司的大量细节回答,我们可以为该公司建立一份个性化的“打分卡”,从而做出投资决策。

我们将演示如何集成 Google(Gemini)与 OpenAI(GPT)等机构的 LLM,以及 Hugging Face 的开源模型,并讲解如何为这些模型配置特定参数。虽然本书前文一直偏重编程,但从现在开始,我们将学习如何自动化地产出生洞见。

8.1 从写代码到用机器学习

在之前的章节中,我们展示了如何分析公司并据此假设哪些公司更适合投资。无论算法和策略如何变化,只要方法建立在“基于证据的决策”之上,我们就能为自己的行为提供正当性。

注意 使用 hypothesize(提出假设)这样的措辞,而不是 judge(判定)等更强的词,可以提醒我们:错误空间始终存在。即便最成功的投资者也曾误判过机会;在波动性资产上,我们很多时候都在依赖假设。对“自己能预测未来”的过度自信是一种自我欺骗,可能带来意外亏损与惨痛教训。

借助在海量历史数据上训练的计算机模型,我们把决策过程在更高层级上委托给算法。模型为何买入或卖出,人类或许并不完全理解——因为它们是“黑箱”。投资者当然乐见能自动化赚钱的高阶交易算法,但一旦行情变化导致交易机器人出现亏损,那就是交易者的噩梦。让我们深入传统 ML 的细节以获得更好的理解。

行为金融学(BEHAVIORAL FINANCE)

Robert F. Shiller、Daniel Kahneman、Amos Tversky 等人的研究表明,投资者常常是非理性的。理解诸如“损失厌恶”等偏差与根深蒂固的行为模式,会让我们反思:情绪和无意识行为是否才是实现财务自由的最大障碍。

这与信息安全很相似:如果“人”是最大挑战,那么“解决人的问题”就是答案。这引出一个有趣的疑问:如果把交易交给计算机,我们能否摆脱偏见?我们将看到,把投资决策简化为 ML 算法以消除“人”的风险,同样面临挑战。

机器学习包含一系列从数据中学习、无需显式指令即可执行任务的统计算法。它们可分为使用监督学习与无监督学习训练出的模型。

监督式 ML 模型用带标签的数据训练。设想一个数据集:列里是关于某家公司的可量化财务数据(称为“特征”),并带有一个标签,表示“一年后该股价更高还是更低”。用监督学习算法训练后,当模型喂入未标注数据时,它就能预测该股会涨还是会跌。随后我们可以把股票标为“买入”“卖出”或“持有”。若与其他股票比较后判断它未来走势可能“超平均”,还可以标为“强烈买入”或“强烈卖出”。这属于分类思路。类似地,还有回归思路:不再给出买卖分类,而是直接估计一年期的百分比涨跌幅(收益率)。

注意 在投资理论中,“因子(factor)”指可能影响交易决策的参数,如价值、规模、动量、质量或波动率等。这些因子通常是数据模型分析数据集中的佳选“特征”。

训练模型需要带标签的数据;那如果数据没有标签呢?无监督学习旨在从数据里找结构——只要能找到有意义的分组方式,就算成功。上市公司股票是无监督学习教科书级的例子:从股价时间序列我们可以提取两个关键值——收益波动率。接下来我们会展示如何绘制这些数据,并通过对图上的点进行聚类来自行“造标签”。

识别离群点——即与其他资产数值明显不同的样本——对高风险偏好的投资者可能有价值:这类资产的行为可能与市场其他部分不同。如果我们坚信某只股票的上涨或下跌假设,就可能选择买入或做空。

投研机构会用 ML 分析股票:它们收集历史数据,预测盈利、营收增长,当然还有股价。金融数据服务商常向投资者提供多家机构预测的“平均值”。图 8.1 展示了基于 yfinance 数据收集而成的 NVIDIA 股价预测。

image.png

图 8.1 基于 yfinance 收集的数据绘制的 NVIDIA 一年期价格预测,分为最高、最低与均值

在这幅图中,我们汇总并绘制了他人的预测。由于“过往表现不代表未来结果”,这些预测可能出错。若要基于分析师预测做决策并提升成功概率,那么关于这些分析师的历史表现细节会很有帮助:历史上更准确的分析师,其下一次预测更可靠的概率也更高。很多付费投研平台的 Pro 订阅服务,核心功能之一就是展示分享观点的分析师的历史业绩。

当然,我们也希望自己建模来做价格预测。在深入这一点之前,先来看看无监督学习的用法。

8.1.1 无监督学习示例

股指常被用作分析个股的入口,因为它们已经对“潜力股”做了初步筛选。比如,标普 500 跟踪了在美国交易所上市的 500 家最大公司。要手动逐一审视这些成分股效率太低。让我们看看能否用 Python 改善这一流程。

如果我们按表现对股票做聚类,再挑对我们更有意思的那一组呢?我们可以先聚焦历史回报优秀的股票,优先探查。下面用代码加载标普数据并按表现进行可视化。以下代码用 Pandas 解析维基百科的 HTML 页面,抓取标普 500 成分股的代码:

sp500_url = 'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies'

data_table = pd.read_html(sp500_url)
tickers = data_table[0]['Symbol'].values.tolist()
tickers = [s.replace('\n', '') for s in tickers]
tickers = [s.replace('.', '-') for s in tickers]
tickers = [s.replace(' ', '') for s in tickers]

第二步,我们加载所有成分股在当年的表现。遍历代码列表,在清单 8.1 中为每只股票加载一年的数据。

清单 8.1 计算收益与波动率

prices_list = []
start_date = datetime.now() - timedelta(days=365)

for ticker in tickers:                              #1
    prices = yf.download(ticker, 
                         start=start_date, 
                         interval="1d")['Close']   #1
    prices = pd.DataFrame(prices)                  #1
    prices.columns = [ticker]                      #1
    prices_list.append(prices)                     #1

prices_df = pd.concat(prices_list,axis=1)
prices_df.sort_index(inplace=True)

returns = pd.DataFrame()
returns['Returns'] = prices_df.pct_change().mean() * 252    #2
returns['Volatility'] = (prices_df.pct_change().std() 
                        * sqrt(252))  #2
#1 加载历史价格数据
#2 计算年化收益与波动率

注意 上述代码里的 252 表示每年的交易日数。证券交易所周末和法定节假日不开市,因此交易日少于自然日。

到目前为止,我们得到一个包含“按年聚合的收益与波动率”的数据结构。收益的目标很直接(我们希望最大化回报),而波动率代表风险:股价波动越大,风险越高。

注意 如果股价在强劲上行趋势中、波动很大,这算风险吗?我们需要验证这只“飞涨”的股票是否处于泡沫,并通过估值比率检查在上涨后的高估值是否仍有基本面支撑。

K-means 聚类是一种向量量化方法,用来把数据划分为多个簇。通过按数值分组,我们可以生成标签。该算法的核心参数是“要分成多少个簇”。所谓“肘部曲线”(elbow curve)能帮助我们确定最优簇数。清单 8.2 展示了如何计算肘部曲线,其结果见图 8.2。

清单 8.2 计算肘部曲线

data = np.asarray([np.asarray(returns['Returns']),
                   np.asarray(returns['Volatility'])]).T
distortions = []
for k in range(2, 20):
    k_means = KMeans(n_clusters=k)
    k_means.fit(data)
    distortions.append(k_means.inertia_)

fig = plt.figure(figsize=(15, 5))
plt.plot(range(2, 20), distortions)
plt.grid(True)
plt.title('Elbow curve')

image.png

图 8.2 肘部曲线:截至 2025 年 5 月 13 日的一年期数据对应的最优簇数

基于该图,我们选择曲线“弯折处”附近的簇数;这个“肘部”表示再继续增加簇数带来的收益(失真度下降)已经不值得额外复杂度的代价,因此是一个较优的参数。在下面的例子里,我们取 5。清单 8.3 使用 K-means 算法生成聚类结果。

清单 8.3 生成聚类

centroids,_ = kmeans(data, 5)

idx,_ = vq(data,centroids)
details = [(name,cluster) for name, cluster in zip(returns.index,idx)]
details_df = pd.DataFrame(details)
details_df.columns = ['Ticker','Cluster']

clusters_df = returns.reset_index()
clusters_df['Cluster'] = details_df['Cluster']
clusters_df.columns = ['Ticker', 'Returns', 'Volatility', 'Cluster']

清单 8.4 展示如何作图。把鼠标悬停在图上点位即可看到各自的股票代码(见图 8.3)。当然也可以直接给每个点加文本标签,但对 500 只成分股来说图面会过于拥挤。

清单 8.4 绘图

fig = px.scatter(clusters_df, x="Returns", 
                 y="Volatility", color="Cluster", hover_data=["Ticker"])
fig.update(layout_coloraxis_showscale=False)
fig.update_traces(
    marker=dict(size=8, symbol="diamond", 
                line=dict(width=2, color="DarkSlateGrey"))
)
fig.show()

image.png

图 8.3 四个聚类的散点图。将鼠标悬停在单个点上可显示其代码。

该示例展示了无监督学习如何按共同特征将股票“分群”。如果我们以交互方式查看此散点图,就能通过逐点探索得出结论。我们可以逐一研究感兴趣的资产并决定进一步深入哪些。例如,关注三个离群点:左侧那个(Moderna)若我们在寻找“有转机可能”的公司,或许值得研究;若想“追求强势延续”的赢家,我们可看右侧高表现点(如 Palantir);而波动率最高的那只,在图中是 Super Micro Computer。无论采取哪种策略,能在图上逐点悬停查看,都会让我们更直观地掌握可选资产之间的差异。

无监督学习帮助我们更好地理解资产。接下来,我们将考察监督学习,看看它是否能够预测股票的未来表现。

8.1.2 监督学习示例

无监督学习通过为海量数据“立结构”来从混沌中提炼意义。一旦拿到了带标签的数据,就该考虑下一步——这就引出了监督学习。让我们用这些标签构建一个分析型数据集,并学习如何预测哪些公司更可能成为“赢家”。

构建分析型数据集(BUILDING AN ANALYTICAL DATASET)

基于前面的散点图,我们可以创建带标签的数据集。每只股票(由其代码 ticker 表示)都属于某个簇(cluster)。在之前探索中“回报最高”的那个簇包含这些代码:PLTR(Palantir)、GEV(GE Vernova)、AXON(Axon Enterprise)、TPL(Texas Pacific Land Corporation)、TSLA(Tesla)、VST(Vistra Corp)、NRG(NRG Energy)、TPR(Tapestry Inc)、AVGO(Broadcom)、PODD(Insulet Corporation)以及 HWM(Howmet Aerospace)。我们可以把这一分组作为数据集中所有代码的标签来源。

现在我们已经有了标识符(tickers)与标签(clusters);接下来需要为这些标识符找到相应的特征。在这个用例中,我们要构建一个二维(2D)的分析数据集,用来在数据上运行某种监督式 ML 算法(例如线性回归)。可以把它想象成一张传统的数据库表:若干列是我们要研究的特征,另有一列是标签/结果;在这里就是“簇”。其中,ticker 充当唯一的主键。我们的目标是用监督式 ML 算法,在足够多的数据帮助下,找出“特征取值”与“标签”之间的相关性。图 8.4 概述了如何用线性回归的监督式 ML 来寻找有潜力的股票。真正的挑战在于:在海量候选中挑出最合适的特征。

image.png

图 8.4 一个带标签的数据集,我们需要为其选择特征。每个特征对应表中的一列。

凡是理论上可能影响股价的可量化要素,都可以成为分析型数据集中的特征。我们可以选择来自财务数据的特征,比如历史股价、费用、盈利等。在特征选择时,也可以远超“企业自身数据”,纳入金融与非金融数据:例如失业率、通胀、经济增长等宏观数据。有些特征还可以对特定行业的 ML 模型“定制”,比如对依赖天气的公司(如农业相关企业),天气数据就很关键。

注意 采用的属性越“专用”,研究范围就越需要收窄。如果把天气作为特征,就应该只纳入那些业务依赖天气数据的公司(如农业)。否则,如果大多数公司与天气几乎无关,反而会加剧“信噪比”问题。

相较于挑特征,选择标签(期望的输出)要容易一些,因为我们的目标很明确:识别股价会上涨的公司。一旦选定了所需特征,我们就用这些特征构建一个时间序列数据集。同时要确定一个合适的时间区间用于评估价格变动。股市高度波动,用 ML 去预测“天级或数周级”的短期走势并不可取。与此同时,某些行业如果时间区间拉得过长也会带来麻烦——区间内发生的结构性变化可能让某些特征失效(比如 AI 的兴起让一些公司的“牌面”被重新洗过)。合理的时间区间候选包括:季度、半年或年度

下一步是采集并汇总历史数据。假设我们决定用“一年”为窗口,那么就收集样本中所有公司的过去一年的数据。有了数据集之后,就可以运行监督式 ML 算法。

当数据量足够时,把样本分为训练集测试集。我们用某个 ML 算法(此处是线性回归)在训练集上训练模型。简化地说,算法会处理数据,识别“特征”与“标签”之间的相关关系。

训练完成后就进入推理(inference):把未标注的数据喂给模型,模型会给出一个可能的结果。由于我们保留了测试集,现在就可以检验模型:模型推理结果与真实标签越一致,模型就越准确。

许多对冲基金的选股方法正是以此为基础。然而,朴素的常识也在提醒我们:如果“用极少数特征就能预测价格、成功又很容易”,那么几乎所有投资书的第一章都会是“机器学习”。用 ML 取得成功有望带来巨额利润,但也非常难。下面具体看看,为什么这个方向的成功远不止“展示级 Demo”那么简单。

我们之前创建的“优胜簇”使用的是“截至 2025 年 5 月 13 日的一年期数据”。该组合覆盖了多个稳定行业(如工业、可选消费)的一系列企业——这些簇包含了价格已经上涨的股票。如果把“数据截至日”改成 1 月 1 日 来聚类,那么“盈利股票”的簇很可能会包含更多科技股。

注意 本书下载区提供的代码允许你使用不同的“结束日期”来创建聚类。

为什么会这样?因为一位新的美国总统及其新政策搅动了股市。当关税政策公布时,那些更依赖国际市场的科技股受到的影响,往往比像 Texas Pacific Land Corporation 这种对国际贸易依赖度较低的公司更明显。因此,我们必须保持灵活,并考虑并行训练多个模型

另一项挑战是数据体量及其相应的数据准备。在示例里我们用的是标普 500——一个“成功公司”的集合。而对冲基金的商业模式是为客户创造高回报,并以此为基金经理带来更高的费用收入。公司规模越小,博取超额收益的机会可能越大。因此,研究范围不应局限于标普 500。围绕“采集与汇总数据”的大数据工程本身就是一门大学问。根据你想支持的特征数量,必须搭建数据管道,从多源加载信息,包括社交媒体、财报文档等等。更大的数据量也意味着处理它们需要更多算力与资源。最后,过拟合是监督学习与 ML 的长期挑战之一:模型依旧需要在“信号”与“噪声”之间做出更好的区分。

总之,如果你有好的点子、具备 ML 能力,依然存在打造“表现优秀”的 ML 模型的空间。不过,为了展示,我们先看看一个更简单的案例。

股价预测(STOCK PRICE PREDICTION)

我们将用一个参考示例来概述这种方法:清单 8.5 使用了随机森林算法。前面的示例中,我们演示了如何使用若干基本面来预测结果——这非常有利于说明监督学习的威力。但在实际操作中,我们希望有一个更简洁、可复现的做法:仅用历史价格数据做一个落地示例。我们和之前一样通过 yfinance 加载数据。关键在于通过设定“下一天的价格”来定义标签(target 列)。由此,我们构造出训练数据集。

清单 8.5 为随机森林加载数据

import yfinance as yf
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from statsmodels.tsa.arima.model import ARIMA
import matplotlib.pyplot as plt

start_date = "2018-01-01"
end_date = "2023-01-01"
ticker ="AAPL"
df = yf.Ticker(ticker).history(start=start_date, end=end_date)
df = df[["Open", "High", "Low", "Close", "Volume"]]

df["Target"] = df["Close"].shift(-1)
df.dropna(inplace=True)

现在进入“训练/测试”拆分。清单 8.6 中,我们先定义特征集 X 与标签 y。使用 80% 作为训练集、20% 作为测试集来验证模型。随后收集输出。变量 rf_rmse 存放均方根误差(RMSE) ,它基于测试集验证反映了模型的准确度。

清单 8.6 随机森林的训练数据

X = df.drop(columns=["Target"])
y = df["Target"]
X_train, X_test, y_train, y_test = train_test_split(X, y, shuffle=False,
                                                    test_size=0.2)
rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
rf_preds = rf_model.predict(X_test)
rf_rmse = np.sqrt(mean_squared_error(y_test, rf_preds))
results = pd.DataFrame({
    "Date": df.index[-len(y_test):],
    "Actual": y_test.values,
    "RandomForest": rf_preds,
}).set_index("Date")

清单 8.7 用于绘图。横轴是日期,纵轴是价格。

清单 8.7 绘制结果

plt.figure(figsize=(12, 6))
plt.plot(results.index, results["Actual"], label="Actual", linewidth=2)
plt.plot(results.index, results["RandomForest"], label="Random Forest", 
alpha=0.7, linestyle="dashed")
plt.title("Stock Price Prediction: Random Forest")
plt.xlabel("Date")
plt.ylabel("Price")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

图 8.5 展示了预测与真实值之间的差异,强调了不准确性会出现,且有时更为显著。如果你做过实验,常会遇到预测不准的情形。有时可以通过引入更多数据来改进;也可以尝试其他 ML 算法,例如 ARIMA(自回归积分滑动平均),在不少场景下可能会得到更准确的结果。

image.png

图 8.5 实际价格与预测价格的差异:可以看到有些时间段预测更准,有些则不然。

一个“可靠的股价预测模型”常被比作“点石成金”(Midas Touch):暗喻能让人快速暴富的能力。虽说确有个别机构(例如 RenTech,稍后我们会介绍)被传拥有这样的本领,但打造高效的股价预测算法极为困难。下面看看具体的挑战。

8.1.3 市场层面的挑战(Market challenges)

金融市场对 ML 用例既有利也有弊。优势之一是:数据质量高、且便于获取经审计的数据。想做 ML 展示的人,相比其他领域,更容易用金融数据做出简单演示

但金融市场也给 ML 带来诸多挑战。先从有效市场理论谈起,再看其他让价格预测变难的因素。

有效市场理论(EFFICIENT MARKET THEORY)

该理论认为:既然投资者能获取所有相关信息,那么资产价格已充分反映其内在价值。因此,金融学里一个最具争议的话题是:长期来看,没有人能仅靠买入低估股票来“持续战胜市场”。巴菲特等跑赢大盘的投资者显然不认同这一点。

即便我们同意“在成熟公司里很难找到被低估的股票”,仍可通过发掘“后来者”的隐藏优势来跑赢市场——而这种优势也许能通过新的分析方法被识别。Hendrik Bessembinder 在论文《Do Stocks Outperform Treasury Bills?》(mng.bz/KwrZ)中指出:历史上大多数股票的累计回报为负;仅少数公司创造了卓越回报,从而使股市整体跑赢了诸如债券等其他资产的平均回报。许多投资者数十年来都在寻找具备“秘制配方”的公司。然而,如果我们希望在 ML 模型里寻找能够揭示公司隐性质量的特征,那么基于过去业绩数字的 ML 往往只能提供有限帮助

随机游走(RANDOM WALK)

“随机游走”描述了股市经常不遵循确定性规律、而呈现混沌行为的现象。巴菲特的导师 Benjamin Graham 用“市场先生(Mr. Market)”的寓言把股市比作一个患有“躁郁症”的人。单一市场(如全球最大的美国市场)的变化就可能波及全球其他市场,进一步增加预测复杂度。因为股价显著依赖于群体心理,试图用 ML 去全球尺度地预测人类情绪,最终会滑向投机——几乎像占星一样。

“非理性繁荣(irrational exuberance)”这一表述出自前美联储主席格林斯潘,并常被耶鲁教授 Shiller 使用——它说明投资者往往并不理性。投资中似有“不成文的规律”:人们会一再变得贪婪,把希望寄托在某个能让他们暴富的新风口上;17 世纪荷兰“郁金香泡沫”就是典型案例。

有些投资者试图以长期投资来对抗“非理性繁荣”。他们研究商业模式和诸如“护城河”等因素,只选择那些能经受住各种市场波动、满足足够质量标准的公司。不过,基于时间序列数据的 ML 算法在这类特定决策场景中的整合机会常常有限,或是需要投入超常的额外努力。出于这个原因,很多基于随机性的策略(如蒙特卡洛模拟)在研究股票时依然很有价值。

社会与技术的长期变迁(SOCIETAL AND TECHNOLOGICAL CHANGES OVER TIME)

一些数据源(例如社交媒体情绪)在久远的过去并不存在。我们几乎不可能像今天这样,去收集“1980 年代公众在某一时间点对可口可乐或其他股票的看法”。

过往公司所处的技术、监管、税制环境都与今日大相径庭:计算机、互联网与 AI 的融入深刻改变了企业运作方式。过去表现优秀的 ML 模型必须再训练并持续改进才能保持竞争力。

几十年前,很少有公司会撰写 ESG(环境、社会、公司治理)报告来强调自己并非唯利是图。在竞争更激烈的年代,“不一味追逐利润最大化”甚至可能被视作弱点。如今,分析师与 ML 模型都会把 ESG 纳入考量;在某个阶段,ESG 表现可能会像盈利结果一样影响股价。

注意 有些分析师认为 ESG 带有政治色彩。公司会根据所在国家的政治环境去调整多元化与环保政策。纯利润导向的投资者,如果发现股价会受到公司不道德行为的影响,也会把 ESG 评级纳入决策。

季节性与经济趋势(SEASONALITY AND ECONOMIC TRENDS)

在第 3 章中我们指出:一年中的不同季度会产生不同的经济产出。对零售等行业而言,圣诞季与暑期的影响截然不同。某些公司如果在年底前新品“扑街”,即便此前几个月数据亮眼,也可能陷入严重问题。

即使我们将模型设定为按年预测股价以绕开季节性,依然要面对经济周期。在衰退期训练出的模型,可能与牛市中训练的模型输出截然不同。像前文提到的 Renaissance Technologies(RenTech)这类专注自动化交易的公司,也会因市场风格切换而面临挑战:曾经“稳赚”的模型可能会在一夜之间变成“稳亏”。

会计实践与管理更迭(ACCOUNTING PRACTICES AND LEADERSHIP CHANGES)

尽管我们在第 3 章中学过:公司必须遵循会计准则,但企业在准则之内对数字的呈现仍有一定灵活性。公司会定期评估战略;新任高管可能采用不同的方法以求超过前任的成绩。为实现目标而负责的团队也会努力“让自己的努力体现在报表上”,以取悦股东。这些不同的会计与经营策略会给 ML 带来挑战。

审视那些存续数十年的公司(如 IBM、通用电气),我们还会发现它们的业务重心会随时间迁移。如果一家公司的整体战略发生了改变,过去还能否作为可用的参照?很可能不能

市场泡沫(MARKET BUBBLES)

历史上存在众多“狂热与泡沫”,在这些时期投资者不再理性。以思科(Cisco)为例,它在 2000 年(互联网泡沫顶峰)股价一度高于 77 美元,此后再也没回到那个价位。我们必须识别这种“非理性繁荣”的阶段,并确保模型能够辨别那些难以持续的趋势。

8.1.4 技术层面的挑战(Technical challenges)

尽管确有少数“冠军”用 ML 取得了惊人的成绩,但同样也有一些公司因为股价预测上的技术难题而选择使用 ML。下面看看其中若干要点。

波动性(VOLATILITY)

图 8.6 展示了一项资产随时间的价格变化。在起点与终点,这项资产的价格与最初相差不大。如果不知道中间发生了什么,我们可能会以为它的价格“很稳定”;然而事实是,中间阶段价格波动很大

image.png

图 8.6 Cosmos(ATOM)在 2021–2023 年间的价格走势

当然,我们始终可以通过收集日度收益、做统计分析,把“波动性”纳入决策因子。但股票的高波动会使 ML 算法更难从中识别出真正强势的资产。

过拟合与欠拟合(OVERFITTING AND UNDERFITTING)

第 3 章提到过大量可用于评估公司表现的比率,这些都可能成为 ML 的特征。除了基本面与技术面(例如股价)外,还有许多外部因素也会影响股价:国家总体经济状况、社交媒体情绪、新闻、天气、内幕交易等等。

如果我们只选很少的特征,就有欠拟合的风险——算法无法识别特征与标签之间强相关;但考虑到潜在特征极多,如果塞入太多,又会走向过拟合。统计学家常说要分辨信号噪声:那些无关痛痒的特征(噪声)会遮蔽我们真正想看到、用于预测结果的因素(信号)。

投入与运维成本(EFFORT)

如果我们需要持续训练与更新多个模型,就必须找到高效的管理实践:模型要版本化,必要时能“回滚/重部署”到历史版本;模型的变更要透明可追溯,以便事后理解其演进。

此外,不同行业与赛道差异巨大(第 3 章已有例证):一个行业有效的模型,放到另一行业可能不好用。于是我们需要为不同的行业/子行业构建专用模型,并并行维护它们,复杂度与维护成本随之攀升。

图 8.7 展示了 MLDevOps 周期:覆盖从数据探索到部署的完整模型生命周期。我们先采集与准备数据,再构建与验证模型;模型通过验证后进行版本化、打包并部署到生产环境。在线上环境中,我们会持续收集新结果,以便回馈评估、精化对模型表现的认知。随着流程推进,还会识别并接入新的数据源,为下一轮模型迭代提供养分。

image.png

图 8.7 MLDevOps 周期:包含准备与部署环节

在大型组织里,维持这些模型所需的投入可能极其庞大,从而拖慢公司的整体进度。造出模型是一回事,把模型长期维护好、避免失控又是另一回事。

8.1.5 缩小问题范围(Narrowing the scope)

一个能准确预测所有股票价格的 ML 模型,犹如童话里的“下金蛋的鹅”;而这类万能的“套利公式”当然并不存在。许多公司在更可隔离的场景里成功落地了 ML。只要用得其所、把握正确目标,超越他人地预测未来收益的机会仍然很多。下面看一个收窄范围的用例。

一个商业模式描述公司如何创造收入并实现经济成功。比如 Netflix 与 Spotify 采用“订阅 + 广告”的营收模式,目标是最大化“每月付费订阅用户”的数量。

我们可以开发特定行业的 ML 模型来衡量“成功”,将通用的宏观经济数据、情绪数据与其他信息源纳入其中,以预测行业层面的结果。这类模型无法消除诸如管理不善地缘政治等风险,但能帮助我们对某个细分市场的可能结果做出评估。

ML 属于判别式模型。我们期望它给出定量结果:如二分类(“是/否”“涨/跌”)或回归值(对某资产未来股价的数值性预测)。设想一个场景:某个 ML 模型建议我们卖出一家我们自己看起来“前景无限”的公司——无论如何,输出的形式仍旧是“买/卖/持有”这类信号;传统 ML 不会解释它的推理过程。那句老话同样适用:“每个场景都有最合适的工具,但不是每个工具都适合所有场景。 ”当场景不需要创意时,判别式 ML 框架大有用武之地。比如你计划打造一个量化交易机器人,基于市场数据自动触发下单,这时传统 ML 足以提供所需价值。接下来,我们将考察另一类 AI——它能生成新的结果,有时也可以称为“更具创造性”的方式,适用于不同的用例。

RenTech 与自动化交易(RENTECH AND AUTOMATED TRADING)

如果你对量化交易感兴趣,不妨研究 Renaissance Technologies(RenTech) 的历史,了解这家公司如何成为全球最成功的对冲基金管理机构之一。其中一个重要的启示(在一本面向程序员讲解投资基础的书里难以完全展开),就是 Jim Simons 及其同事为取得成功所必须跨越的重重难关。

很容易想象:你盯着屏幕,为你的模型跑赢市场而欢呼。但你也必须看到另一些时刻:上周还在赚钱的模型,这周突然开始亏损。周围的人都会问同一个问题:为什么? 而在 ML 的语境下,你往往无法立即给出答案

8.2 从机器学习到生成式 AI(GenAI)

ML(机器学习)通常对应特定用例。以判别式 AI 为代表、为股价预测而训练的模型,无法直接用于其他场景。与我们之前看到的判别式模型相反,GenAI 追求更通用的应用。显而易见,为医疗等不同场景训练的 ML 模型不可能去预测股价;但如果我们向一个公共 LLM(如 OpenAI GPT 或 Google Gemini)提出任何问题——无论是金融还是其他话题——在多数情况下,我们都会得到听起来还不错的回答。

那么,GenAI 的不同之处在哪里?显而易见的答案是:就聊天类用例而言,用 LLM 生成答案属于高级 NLP(自然语言处理)范畴,它的目标、技术与应用与“用线性回归去预测股价趋势”的用例本质不同。若把传统 NLP 比作家猫,LLM 则像大型猫科;但若再把基于 LLM 的 GenAI 与传统 ML 相比,就像把放在一起比较——二者同属哺乳动物(就像 LLM 与 ML 同属“分析”大类),但依然是截然不同的“物种”。

反过来说,我们之前在“混沌领域”(如股价)中也探讨了计算机生成模型的可能局限,这有助于我们在研究另一类分析领域时知道该留意什么。GenAI 虽然是“不同物种”,但仍属于计算机生成模型,值得考察相同的局限是否同样适用。

本书不会展开技术细节,但可参考两本阐述Transformer 与注意力机制如何成为“变革者”的书:Amit Bahree 的 Generative AI in Action(Manning,2024;www.manning.com/books/gener… Numa Dhamani、Maggie Engler 的 Introduction to Generative AI(Manning,2024;www.manning.com/books/intro… Is All You Need》(mng.bz/Pw55)提出了构建文本模型的改进思路——不再穷举句中每个词之间的关系,而是聚焦关键词之间的关系,这催生了Transformer。该思路使我们得以在海量数据上训练,奠定了拥有数以百万计参数的 LLM 的基础。

8.2.1 比较 LLMs(Comparing LLMs)

先做个实验:我们向 GPT-4o、Gemini 和 Finance Chat 询问投资策略,给出以下三条与投资相关的提示词,比较它们的回答差异:

  1. 当前股市的趋势如何?
  2. 基于沃伦·巴菲特(Warren Buffett)的投资策略(且不在其现有持仓中),请给出三个可供参考的标的;
  3. 基于彼得·林奇(Peter Lynch)的投资策略(且不在其现有持仓中),请给出三个可供参考的标的。

本章对结果做了总结,强调 LLM 并非完美无缺。本次测试在 2024 年 6 月执行,之后市场在 2024 年 8 月出现回落并大体修复。需要注意的是,使用 LLM 的一个挑战是非确定性:不同用户可能因为所用模型与参数不同而得到不同答案。

总结答案(SUMMARIZING THE ANSWERS)

尽管 Gemini 与 GPT 也表达了担忧,但所有 LLM 整体上都描绘了积极的市场前景,并建议投资者分散化配置——这与大多数投顾的“标配建议”一致。没有任何一个 LLM 给出能让我们规避 2024 年 8 月“波动”的策略。有些建议(如被动投资)固然可取,但这本就是面向新手最常见的推荐。

针对巴菲特与林奇这两位投资者的特定策略提问,答案更具结论性:彼得·林奇在退休前是成长型投资者;沃伦·巴菲特以价值投资著称。表 8.1 展示了结果。

表 8.1 与个股相关提示词的结果(Results of prompts related to stocks)

InvestorGPT-4oGeminiFinance Chat
BuffettMicrosoft, Costco, VisaCostco, Microsoft, Procter & GambleAllegion, Danaher, Coca-Cola
LynchEtsy, Zoom, SquareTrade Desk, Etsy, ShopifyTesla, Allegion, DCP

结果解读(INTERPRETATION OF RESULTS)

一些媒体(如 The Economist)在 2024 年 7 月提醒投资者警惕市场可能高估。虽然可以承认 LLM 大致能感知波动,但它们尚不足以像 Financial TimesWall Street Journal 等媒体文章那样给出有定论或足够细节的市场观察;更稳妥的做法仍是咨询专业人士而非依赖 LLM。

在投资者比较方面:GPT-4o 与 Finance Chat 返回了已在伯克希尔·哈撒韦(Berkshire Hathaway)持仓(www.cnbc.com/berkshire-h… 与 Coca-Cola)。GPT-4o 与 Gemini 对巴菲特的选择中两次出现了相同公司(Microsoft、Costco),并在彼得·林奇的选择上有一次重合(Etsy)。GPT-4o 还选了在 2021 年已更名的公司(Square),并选了与新冠疫情密切关联的公司(Zoom)。Finance Chat 则两次选中了名为 Allegion爱尔兰公司。

这些测试凸显了寻求投资建议的风险:GPT-4o 与 Gemini 之所以给出相同股票,是不是因为数据来源相同?这些数据有多新?Finance Chat 为何两次选中 Allegion?三个模型究竟训练于哪些数据

8.2.2 用 GenAI 补强 ML(Complementing ML with GenAI)

GenAI 与传统 ML 难以直接比较,因为二者在某种程度上目标不同:ML 更凝练克制,而 GenAI 更像一把多功能军刀,用于解决带有“创造性”的问题。二者可以配合使用:例如用 GenAI 做 ML 模型的研究助手。ML 的核心是训练一个模型,接受数据、考察特定参数,并基于历史数据预测结果;而一个挑战是如何选对参数并维持好模型。

能给出更通用答案的 GenAI 可以加速研究过程,帮助识别适合进入 ML 模型的候选特征。简而言之,不要在“传统 ML GenAI”之间二选一;在探索中考虑把两者结合起来。

8.2.3 挑战(Challenges)

结合小实验与已有认知,我们可以梳理使用 LLM 做投资建议时面临的挑战。其中一些对于做出明智的投资决策至关重要,它们会直接决定你是盈利还是亏损。几乎没人希望因为 LLM 的“大胆猜测”而亏钱。

过时信息(DATED INFORMATION)

想象你在寻求投资建议,而模型训练所用的数据过旧;与此同时,互联网上刚出现一篇揭示某资产潜在风险的新文章,而 LLM 可能尚未纳入这条信息。

幻觉(HALLUCINATIONS)

归根结底,LLM 是由数十亿参数构成的模型。模型维护者主要用来自互联网的海量数据对其进行训练。LLM 可能给出颇有见地的建议,帮助你获得不错的回报;但也可能给出可疑的答案。

8.2.4 对 ML 与 GenAI 的最终判断(Final judgement on ML and GenAI)

传统 ML 也被称为判别式 AI。判别式强调“区分、分离”,而生成式则追求创造性输出。ML 更聚焦于从数据中针对特定用例提取结果;GenAI 的应用更广泛,也更可能产生出乎意料的结果。两种方法的路径不同,但当投资分析的范围过宽时,结局相同:在高波动环境下相信任何预测都存在风险。切记:过往表现不代表未来结果

正如我们所示,两种方法在收窄范围内都能提供价值;因此,接下来看看如何在我们的金融研究中使用 GenAI。我们将指出:只要用法得当,GenAI 在经济研究中是能创造价值的。

8.3 GenAI 的实用方法(Practical use of GenAI)

GenAI 提供了多种寻找高回报资产的途径。本节列出其中若干。请注意,GenAI 仍在快速演进中;新的意外创新不断出现,为投资者带来新的可能性。继续探索用 LLM 优化结果的新方法。第 9 章我们还会介绍一些更进阶的用例。

8.3.1 将 LLM 作为研究助理(Using LLMs as research assistants)

LLM 能显著缩短执行耗时任务的周期,尤其是需要查阅大量资料的研究类工作。与其泛泛而问“现在最值得买的股票是什么”,不如提出需要 LLM 去挖掘明确细节的问题。举例而言,构建“买入决策打分卡”的一个关键细节就是公司管理层的管理业绩。借助 LLM,我们往往能比逐个在 LinkedIn 检索管理者更快地获得该公司的高层摘要。类似地,未决诉讼内幕交易商业模式客户分层等,也能快速初筛。传统的网页检索可能需要数小时的工作,LLM 往往数秒即可给出一个初步答案。下面深入两个用例。

文档总结(SUMMARIZING DOCUMENTS)

投资需要大量的阅读与思考。许多专业投资者(如巴菲特)把大量时间用于阅读并收集公司信息。公司会发布冗长的文件,我们也能获得各类电话会与路演的文字实录。逐字读完耗时巨大。

一个具体用例是:把这些文档交给 LLM,并要求按你的关注点进行摘要。例如,把一份 60 页的文档总结为一页纸的关键信息

代码生成(CODE GENERATION)

本书给出了大量用于分析股票的代码。同时,任何有兴趣的程序员都可以从 LLM 处获得不少算法。LLM 能生成实用且有意义的代码,从数据采集、比率计算到 ML 使用,帮助你更快完成编程。

非财务风险的宏观评估(HIGH-LEVEL ANALYSES OF NONFINANCIAL RISKS)

第 7 章指出:用算法评估多种非财务风险会带来可观工作量,因为“非财务风险”范畴很广、定义并不统一。我们可以利用数据来预测疫情、战争、自然灾害对个别公司的影响,并发现它们之间可能存在传导。但若做细致评估,投入会非常大。于是需要自问:我们的分析必须精确到何种程度?对个人投资者而言,也许宏观层面的整体评估已足够,用以验证 LLM 的输出。

你可以提交类似提示词:“假设风险评分从 10(最高)到 0(最低),我想评估我投资组合中每个资产在疫情全球贸易战气候变化方面的风险。每项至少给出一句话理由。如果无法关联该风险,也请明确说明‘数据不足’即可。”

表 8.2 是作者向 GPT-4o 提问后获得的参考结果,并转录成表格。你可以用类似提示词为自己的组合得到类似的初筛分析。

表 8.2 由 GPT-4o 提供的参考风险评估(0 最低,10 最高)

CompanyPandemicReasonTrade warReasonClimate changeReason
Google2数字服务在疫情中表现更好。6全球广告投放受地缘摩擦影响。3直接气候暴露度较低。
Pfizer4新冠初期受益高,后续边际减弱。3出口脆弱性有限。2整体环境风险较低。
Ali Baba5疫情早期中国消费下滑。9中美科技脱钩的核心角色。6物流链存在一定碳排放暴露。
Orsted1可再生能源需求稳定或上升。2本地化风电/绿电项目限制了外部暴露。9业务与气候政策强相关。
CCJ1铀需求稳定。4面向出口但属关键材料。6气候紧迫性提升有利于核能。
Lyft8封锁期出行需求大幅下滑。3主要是美国本土业务。4排放监管存在一定转型风险。
MNMD3疫情期间临床试验可能延迟。1全球出口相关性低。2几乎无气候相关暴露。
Uber6疫情期打车降、外卖升。5全球运营,受贸易摩擦影响。4电动化目标带来转型压力。
TSM3首波疫情需求下滑但恢复较快。10中美芯片博弈的关键战场。5能源/用水足迹带来一定议题。

专业的风险分析师会指出,这类评估过于粗略,专注于风险的机构通常能给出更好且经同行评审的结果。尽管如此,LLM 的这类评估对个人投资者可能已足以帮助其回顾与微调策略。在上面的示例汇总中,我们为疫情打了 33 分、为贸易战 43 分、为气候变化 41 分。尽管这些评分源自 LLM 的估计,投资者仍能据此识别自身可能面临的特定风险敞口并采取相应行动。例如,如果发现组合对“疫情风险”的暴露偏高,那么在听到可能出现新一轮疫情的消息时,就会采取更谨慎的态度。

8.3.2 将 LLM 集成到代码中(Integrating LLMs into code)

各家 LLM 提供商在市场上竞争以获得更多用户关注。有些 LLM 还会提供不同的产品版本,功能或强或弱。即便某个最新版本在一段时间内更为强势,厂商也会不断发布带有新功能的新版本,这种“统治地位”很快就会被打破。

公开的 LLM(如 OpenAI 的 GPT、Google 的 Gemini、Meta 的 Llama)都支持通过 API 提交提示词(prompt),我们可以在 Python 代码里调用这些 API。我们把提示词发给模型,得到回答,再进行后续处理。我们还会演示:当把 Hugging Face 上的模型下载到本机运行时,与直接调用云端模型有何不同。

OPENAI

作为程序员,我们更希望通过 API 向引擎提交提示词,把结果取回变量里,而不是把请求粘贴到聊天框里。清单 8.8 给出了面向 OpenAI GPT 模型的示例代码。要运行这段代码,你需要一个 OpenAI 账户API Key。变量 system_content 用于设定 GPT 的“回答风格”之类的通用参数;你可以要求它“简洁作答”或给出其他行为约束。用这段简单代码,我们提交一个提示词,并获取 LLM 的返回结果进行评估。

清单 8.8 通过 OpenAI API 提交提示词

from openai import OpenAI

client = OpenAI(
  api_key=api_key
)

completion = client.chat.completions.create(
  model="gpt-4o",
  messages=[
    {"role": "system", "content": system_content},
    {"role": "user", "content": question}
  ]
)

通常,最新的模型会给出最佳效果。但在某些场景下,使用更小的模型能降低时延单词成本,更合适。例如,如果我们更看重成本或时延,就可以用 GPT-4o mini 替代 GPT-4o

聊天补全(chat completions)方法有很多参数(mng.bz/rZDj)。API不断演进,建议留意是否有新的可用选项。

值得尝试的一个参数是 temperature:它决定回答中采用“低概率词元”的程度。温度越高,输出越随机。我们可以把 temperature 看作“风险刻度”,若你厌恶风险、不希望 GPT“自由发挥”,就把它设为 0

有了与 OpenAI 的接口,我们就能在 Jupyter Notebook 中提出各类问题。不过,就像咨询人类顾问一样,对比“多位专家”的意见也很有帮助。因此,接下来看看如何把 Google Gemini 集成到 Python 代码中。

GEMINI

把 Gemini 的基础 API 调用集成到 Python 中相对比 GPT 更简单。清单 8.9 展示了如何用 Gemini 发起提示。同样可以选择不同的模型版本;只需发送问题并解析返回值即可。

清单 8.9 通过 Gemini API 提交提示词

model = genai.GenerativeModel('gemini-1.5-pro-latest')
response = model.generate_content("Perform Porter 5 Forces Framework "
.                                 "analysis on NVIDIA")
print(response.candidates[0].content.parts[0])

上面的示例使用了 gemini-1.5-pro-latest。按复杂度划分,还有 Ultra、Pro、Flash、Nano 等型号。Nano 面向算力受限环境(如移动设备)。在写作本书时,只有 1.5 版本的 ProFlash 可用,因此在新的 Ultra 发布之前,Pro 是最强模型。

我们也可以添加配置参数。清单 8.10 中,我们限制了响应的 token 数,并设置了 temperature,用于控制 LLM 的“创造性”。

清单 8.10 带参数地向 Gemini 提交提示词

response = model_flash.generate_content(f"Perform Porter 5 Forces"
.                                        "Framework analysis on NVIDIA",
                                        generation_config = genai.GenerationConfig(
                                        max_output_tokens=max_token,
                                        temperature=temperature,
                                    ))

集成 GPTGemini 都很容易。我们还可以考察接入其他 LLM 是否同样简单。下面先看两个模型,然后再把目光转向开源模型替代方案。

其他 LLM(OTHER LLMS)

清单 8.11 展示了 Anthropic 提供的一系列 LLM(Claude)的 API。示例中已经包含了 max_tokenstemperature 参数。只要有有效的 API Key,Python 程序员就能把这段代码嵌入任意脚本运行。可以看到,这些参数与其他 API 大同小异

清单 8.11 通过 Anthropic API 提交提示词

client = anthropic.Anthropic(api_key=key)
message = client.messages.create(
      model="claude-3-opus-20240229",
      max_tokens=1000,
      temperature=0,
      system="You are Claude, an AI assistant.",
      messages=[
          {"role": "user", "content": question}
      ]
 print("Claude's response:", answer.content)

如清单 8.12 所示,Mistral(法国公司开发的 LLM)也表明集成其 API 同样直观。方法名可能略有不同,但本质都一样:选模型 → 设参数 → 发送问题

清单 8.12 通过 Mistral API 提交提示词

model = "mistral-large-latest"
client = Mistral(api_key=api_key)
chat_response = client.chat.complete(
  model = model,
  messages = [
    {
      "role": "user",
      "content": question,
    },
  ]
)
print(chat_response.choices[0].message.content)

不过,以上这些 LLM——即便只是简单片段——有一个共同点:开发者需要获取 API Key 才能使用。LLM 背后的公司需要通过其模型变现,这意味着:部分 LLM 只有在付费订阅的实体提供了 API Key 时才可访问。

同时,这些 LLM 都托管在厂商的基础设施之上。假设你要做一家开发复杂投资策略的 fintech 创业公司,程序员可能不愿意自己的请求被第三方“看到”。他们会更倾向于在自家环境中托管 LLM。

正如我们所见,不同提供商都有各自的 API。程序员自然会希望只用“一套 API”,通过参数切换模型。在第 9 章,我们会介绍 LangChain,它就提供了这样的能力。

FINANCE CHAT

演示完如何把商用 LLM 接入代码后,我们看看如何集成针对金融场景训练的开源 LLM。Hugging Face 已经成为托管开源 LLM 的首选平台。

注意 对经历过 1990 年代末“开源 vs 闭源”之争的工程师来说,如今关于“开源 vs AI”的讨论多少像是那场争论的续篇。只是名字变了:不再是 Windows 对 Linux、Bill Gates 对 Linus Torvalds,而是商用产品Hugging Face,或 Sam Altman 对“一群在其权力受质疑时希望将其移除的工程师”。

开源 LLM 面临与开源软件系统相同的机遇与挑战。虽然它们的直接营收可能低于商用授权软件,但往往获得学术界的支持。开源拥护者也宣称其伦理立场更优:源码与架构公开可见,开源 LLM 的提供者通常也会对训练过程提供更多透明度

金融相关的 LLM(FINANCE-RELATED LLMS)

有些 LLM 是为特定领域而训的。Bloomberg GPT 就是以金融数据训练的知名案例。由于 Bloomberg GPT 是商用 LLM,本节不纳入评测。

另一种增强“金融知识”的路径是:用金融数据微调(fine-tune)已有模型。比如,ML 工程师可以收集公司财报电话会的文字实录(高管讨论财务结果),把这些数据拿来微调现成的 LLM。这样,模型在保留原有知识的同时吸收新知识。我们会在第 9 章展开。

从程序员视角看,使用开源模型最大的不同在于:通常我们把模型加载到自家基础设施上并在本地推理,而不是调用远端托管的 LLM。清单 8.13 使用了 AdaptLLM/finance-chat(Hugging Face 地址:huggingface.co/AdaptLLM/fi…)。如果本地尚未下载模型,运行示例代码会自动拉取模型,然后在本机执行推理。首次运行时请注意:下载模型可能需要一定时间

清单 8.13 使用开源模型执行提示词

from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

def ask_huggingface(model_name, query):
    model = AutoModelForCausalLM.from_pretrained(model_name)
    tokenizer = AutoTokenizer.from_pretrained(model_name)

    our_system_prompt = """\nYou are a helpful, respectful and honest 
assistant. Always answer as helpfully as possible, while being safe.  Your 
answers should not include any harmful, unethical, racist, sexist, toxic, 
dangerous, or illegal content. Please ensure that your responses are 
socially unbiased and positive in nature.\n\nIf a question does not make 
any sense, or is not factually coherent, explain why instead of answering 
something not correct. If you don't know the answer to a question, please 
don't share false information.\n"""
    prompt = f"<s>[INST] <<SYS>>{our_system_prompt}<</SYS>>"
             f"\n\n{query} [/INST]"

    inputs = tokenizer(prompt, return_tensors="pt", 
                       add_special_tokens=False).input_ids.to(model.device)
    outputs = model.generate(input_ids=inputs, max_length=4096)[0]

    answer_start = int(inputs.shape[-1])
    pred = tokenizer.decode(outputs[answer_start:], skip_special_tokens=True)
    return pred  

question = "What is the current trend in the stock market?"
model = "AdaptLLM/finance-chat"
response = ask_huggingface(model,  question)

使用 Hugging Face 可以避免商用 LLM 的费用。但代价在于:如果在本地运行模型,你首先需要相应硬件支持,包括足够的磁盘空间可执行模型的处理器/显卡

推理耗时会取决于本机硬件——根据你为模型提供的 GPU 数量,可能需要几分钟。同时别忘了:你可能还需要花时间安装额外的 Python 库

8.4 提示工程(Prompt engineering)

许多 YouTube 视频都在教大家如何优化提示词(prompt)。这个听上去像一门“复杂学科”的东西——尤其冠以 engineering(工程)之名——可能显得很高深,但它的核心问题其实很简单:别只想问“问什么”,还要想“怎么问” 。你把需求说明得越清楚、提供的上下文越充分,得到的回答就越好。应用提示工程并不需要工程学位,但它也许是用 AI 获得更佳结果的**最大“低垂果实”**之一。让我们先从定义投资者画像开始。

8.4.1 投资者画像(An investor’s profile)

想象一个陌生人走向人类理财顾问,抛出一个很泛的问题:“请给我配一个好点的投资组合。”专业的投顾在不了解客户更多信息前,是不会给出任何建议的。优秀的顾问会通过精心准备的问题引导客户说出他们的风险承受能力投资目标等关键信息。

同理,若给出更多上下文,LLM 也会提供更有分量的答案。下面这个问题就是对前述“泛问法”的首次改进:

我是风险厌恶型投资者,想投资股票。目前我有 100,000 美元可用于投资。我的目标是最大化被动收入。我只想投资信息技术(IT)板块的公司。你能为我给出一个在“回报最大化、风险最小化”意义上的参考投资组合吗?

当输入发送给 LLM 后,它会被分词/标记化。LLM 会把其中一些标记识别为关键词。在我们的例子里,这些词可能包括“风险厌恶型投资者、股票、信息技术板块、最大化回报、最小化风险”。我们越多地使用领域术语,越可能获得更好的回答——因为 LLM 训练所用的高质量语料通常来自领域专家,而他们也使用这些术语。

TIP 阅读 Financial TimesThe Wall Street Journal 等报纸的投资版块,理解特定术语的含义,是简单却强大的提问增益方式。下次别只问“为什么股市涨/跌”,试着问它为何“暴跌(plummeted) ”或“飙升(soared) ”。

当你开始投资时,关于公司或机会会有很多研究性问题。你大概不愿意在每个问题里都重复同样的背景信息。

一个优秀的人类顾问会为你做笔记,但时间一长也可能遗忘细节:他们有时会为一家高速成长的“明星初创”兴奋不已,却太晚才意识到该机会与客户的风险画像不匹配;另一次,他们建议了某只海外 ETF,却忘了客户的税收居民身份会触发预提税问题。这类疏忽会让你花钱买教训。

这正是 LLM 的明显优势所在:它不会忘记。一旦你提供了上下文,它会在随后的交互中保持一致——除非你明确移除或修改。不同于可能忽略细节的人类顾问,AI 会持续按照你的参数行事,确保每条建议都严格遵循你的偏好。

建立上下文是用 AI 获得理财指引时最首要、最关键的一步。这个上下文定义了你的 AI 助手在分析投资时将遵循的“规则”。让我们看一些参数,并探讨如何在对话中加以设定。你可以把下面这些要点视为一份模板,整合成一段“关于你的通用说明”,提供给 LLM 作为背景知识

目标(GOALS)

尽可能精确地陈述你的目标。你为什么要投资?很可能不只是因为朋友让你试试股票。你是要成为“击败市场的少数奇才”,还是选择耐心增长,每年获得足以维持合理生活的被动收入

许多投顾会建议你量化目标。你心里有个具体数字吗?这就引出了下一个问题:为了实现目标,你愿意承担多大风险?

风险偏好(RISK PREFERENCE)

设想你做了一笔高风险交易:顺利的话赚 30% ,不顺的话亏很多。有人照睡如常;也有人辗转反侧、焦虑担忧。

把自己说得比实际更“大胆”。历史上许多成功的投资者,恰恰是因为谨慎而成功。

了解你的风险偏好需要强烈的自我认知。你越了解自己,你的“画像”就越精准

经验(EXPERIENCE)

巴菲特的“金科玉律”:只投资你理解的东西。把“你懂什么”写进去,可能是投资组合里很好摘取的“低垂果实”。例如:“我是程序员,供职于金融服务行业。”你甚至可以写上曾任/现任雇主合作紧密的客户

此外,明确你对哪些资产更有经验;如果你不想持有某些资产,也请写明。加密货币就是一个有分歧的例子——想要或不想要,都要说明。

税务考量(TAX CONSIDERATIONS)

告诉 LLM 你的国籍税收居民地,它就能给出一些通常需要税务顾问才能得到的细节建议。别犹豫,直接写:“我是 X 国公民,税务居民在 Y 国,我需要一个尽量减少税务成本的组合。”记住 LLM 可能会幻觉,把税务建议再与人类顾问交叉核验总是明智的。

伦理或个人偏好(ETHICAL OR PERSONAL PREFERENCES)

有的投资者把宗教/伦理/政治观点与投资切割;对另一些人而言,这反而是策略中最关键的部分之一。若投资于与你价值观不符的公司会让你不适,请写明。无论你关注气候变化、政治、堕胎法、动物权益或其他议题,都说出来——毕竟这是你的钱。

你也可以通过提示工程来调节回答风格:有人偏好详尽解释,有人更喜欢简洁直接。下面是一份参考画像示例:

I have a computer science background. I have 
worked on various digital transformation projects 
for multiple companies. I understand well how AI 
can change companies' businesses. I am looking  #1
for companies' stocks that might be transformed 
through AI but have not yet been overrun by 
investors.                                           

I aim to achieve financial independence within the 
next five years. I have approximately 500,000 USD 
available for investment. I want to be able to    #1
calculate the money I make passively, considering 
the average yield of my assets (interest, staking 
rewards, and dividends).                             

I mainly hold stocks and ETFs. I also have bonds 
and crypto. I want to keep some amount in index 
funds.                                              #2

I am interested in the future of autonomous 
driving and the monetization of climate change 
mitigation. I also believe in the increasing demand 
for reliable, nonvolatile energy sources, such as  #3
nuclear energy, driven by the growing need for 
sustainable energy solutions. I am also open to 
alternative sources of energy, including atomic 
energy.                                            

I use Interactive Broker and Alpaca as brokers. 
I use cold wallets to store cryptocurrency.        #3

I have uploaded a text file with all the stocks 
I hold. It is called stocks.txt and shall be       #3
included in the research if needed.                

I can take risks if decisions have been thoroughly 
researched. If the valuation of the asset is 
temporarily lower, I have no problem as long as 
I see long-term potential. I am okay with shorting  #4
some positions, but I prefer long-term quality 
investing. I do not do day trading.                    

I want to diversify. Diversification also includes 
assets worldwide, as I see political risks in the US.   #4
Otherwise, I am fine with holding most assets in the 
US market.                                             

I am a US American citizen. My tax residency is in 
the UK. I want to minimize the taxes I have to pay.   #5

I do not like to invest in the tobacco industry 
and companies that ignore animal rights.   #6
#1 Background
#2 Experience
#3 Experience
#4 Risk
#5 Taxes
#6 Ethics

8.4.2 用提示词寻找可投资的公司(Using prompts to find companies to invest in)

成长型投资者常常寻找小盘股,希望它们在未来数年里有较高概率实现营收的大幅增长。那么,我们能否通过向 LLM 提交提示词来找到这些公司?前提是:把目标定义清楚。下面用一个参考示例来说明。Netflix 的商业模式相当简单(见图 8.8):每月订阅 Netflix 的用户越多,公司赚得越多。如果我们预测订阅收入能够超过各项成本,Netflix 就会盈利;若利润持续增长,股价大概率也会上涨。

image.png

图 8.8 一个高度简化的模型:当付费订阅带来的收入超过内容制作版权许可成本时,Netflix 即可盈利。虽然后台报表还会受到很多其他数字影响,但此类示意有助于抓住对一家公司的长期成功最具决定性的关键数字。

预测 Netflix 的成本可能很难,因为这需要深入了解内部拍摄项目与版权谈判,而这些信息我们并不掌握(除非你在 Netflix 工作)。不过,我们可以借助 LLM 来估计订阅用户的增长

哪些因素会影响订阅人数?我们需要找出吸引与留住用户的要点。举例来说,用户有时会形成锁定效应:片单里“待看”的节目排得很满;孩子们习惯了家庭账户中的节目,家长若贸然取消订阅可能会引发“家庭危机”。再比如,一些家长希望保留平台提供的观看记录与监督功能。这样的业务既有持续增长的可能,又具备厂商锁定/经济护城河(moat,投资领域常用词),对投资者而言近乎“天堂”。观察股价在业务从“寄送 DVD”转向“流媒体”之后的演变,尤为耐人寻味。

Python 还是聊天机器人(PYTHON OR CHATBOTS)

一些尝试 LLM 聊天机器人的用户会发现,它们在研究资产时很有用。某些聊天机器人在收到提示词后还会提供附加研究选项。于是一个合理的问题是:我们还需要 Python 吗?第 9 章将详述。此处先概括独立聊天机器人尚未解决的几点:

  • 多数机器人不提供专门面向金融用例、带向量化数据的 RAG(检索增强生成)。
  • LLM 可能忽略小公司或知名度较低企业的数据,从而错漏关键信息
  • 无论使用哪家服务,结果通常存放在对方基础设施上,跨平台统一管理资料会很难。

因此,聊天机器人能帮助我们回答很多问题;但如果我们想联用多个 LLM注入特定外部数据,通常仍需要一些代码来完成。第 9 章我们会演示如何使用AI Agent

尽管 Netflix 的商业模式足够吸引,但它可能不再处于高速成长期。如果我们把“Netflix 成功的关键要素”写成提示词,能否找到相似特征的公司呢?

我们给 LLM 的上下文与细节越多,得到的回答越具体。先用一个检查清单看看我们的提示词还能如何改进:

  • 是否足够具体? 明确你要什么;也可以指定回答的语体/风格(正式或非正式)。
  • 表达是否简洁? 含糊或冗长的措辞会降低效率。
  • 能否提供示例? 给出“你想要的样子”的样例,效果往往更好;可参照你熟悉且看好的公司类型。

下面为“寻找类 Netflix 公司”拟一个提示词;我们可以调用不同 LLM对比结果:

我想找到那些早期 Netflix 式前景的公司。我希望低位买入、若干年后高位卖出。这些公司应当具备全球化扩张能力面向 C 端订阅(B2C subscription)的模式,并拥有强经济护城河。它们应当仍有增长空间,且已在交易所上市。请给出三个示例并说明你的选择理由

ChatGPT 返回了 DuolingoBumble 等结果——在 Seeking Alpha 上,一些投资者认为这些标的风险较高。请牢记:LLM 的推荐只是进一步研究的起点。不做尽调就直接投资风险极大。你必须自己判断 LLM 的答案是否站得住脚

总结(Summary)

  • 可以把 ML 算法 作为代码片段集成到 Web Notebook 中,用于金融研究(例如预测股价走势与上行趋势)。
  • 无监督学习 有助于识别离群点——在投资场景中,可能对应“与大盘/同业不同”的公司,从而带来机会。
  • 可以用无监督学习为监督学习寻找潜在标签
  • 监督学习 能通过分析历史数据来预测公司未来表现
  • 成功应用监督学习需要较强技术能力:从多源数据采集到规模化算法处理均是难点。
  • 市场受多因素影响(基本面、技术面及其他与单个公司无关的数据),多数模型都面临过拟合或欠拟合的风险。
  • 有效市场理论 认为多数资产的市场价格已反映内在价值
  • 随机市场理论 与“市场先生”寓言表明市场难以预测,这增加了 ML 建模的挑战。
  • 技术与社会变迁 会影响投资策略(例如当今投资者更重视 ESG 规制)。
  • 季节性与经济周期 会影响股票表现,ML 模型必须考虑这些因素。
  • 会计口径差异 使跨公司比较更困难。
  • 要有效整合 ML,我们需在各行业投入大量精力以识别模式并反复再训练模型;真正大获成功的 ML 用例在对冲基金中只占一小部分
  • LLM 是 NLP 的“游戏规则改变者”,采用注意力机制聚焦关键词关系,使得超大参数规模模型成为可能,并可作为通用主题的聊天机器人。
  • LLM 可以定向训练/微调以回答特定主题(包括金融与投资)的提问。
  • LLM 也擅长给出非财务风险对个别公司的影响概览;但需警惕幻觉,必要时复核输出。
  • 用户可在多种 LLM 中选择;通过 API 发送查询到 LLM 并不复杂,通常只需一个 API Key 来鉴权、在提供商基础设施上完成推理。
  • 许多 LLM 存在不同版本/体量:有的需要付费订阅,有的面向低算力环境(如手机)。
  • LLM 可分为开源专有:开源模型可下载到本地/计算节点上做推理;专有模型在提供商侧执行。
  • AI 伦理 从业者担心专有 LLM 可能滥用用户问题中的信息,且其信息采集的透明度存在争议。
  • 无论开源或专有,LLM 都能提供投资灵感;但在未尽调前贸然押注 LLM 的投资建议是高度投机的。
  • LLM 很适合充当研究助理:当研究耗时减少,投资者就能把更多精力用于决策
  • LLM 的代码生成能力帮助程序员更高效地写代码,用 Python 等语言在多场景下分析投资。
  • 虽能用 LLM 产出投资想法,但它的核心价值在于辅助尽调:为既有想法补齐细节,构建个人打分卡以做出更有根据的买入决策。
  • LLM 加速金融研究的同时,也会犯错并产生虚构信息(幻觉)
  • 问题不是“选判别式 AI(传统 ML)还是 GenAI”,而是如何务实地按场景使用它们,并把二者结合
  • 提示工程 是一门提升 LLM 输出质量的“问法”学:让用户能传递更多细节、示例与上下文。
  • 提示工程不能替代常识:我们仍需明确“自己究竟想知道什么”,避免对 LLM 提出过于笼统的问题。
  • 建立包含目标、风险承受、税务居民地等信息的投资者画像,能帮助 LLM 给出更精细的回答。
  • 向 LLM 提交提示词时,务必越具体越好、上下文越足越好;提供参考示例会更有帮助。