news 2026/10/12 14:06:51

tf-quant-finance LSM 最小二乘蒙特卡洛算法:用 Longstaff-Schwartz 回归法为美式期权定价

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
tf-quant-finance LSM 最小二乘蒙特卡洛算法:用 Longstaff-Schwartz 回归法为美式期权定价
  • 金融科技
  • 科学计算

【免费下载链接】tf-quant-finance

High-performance TensorFlow library for quantitative finance.

项目地址:https://gitcode.com/gh_mirrors/tf/tf-quant-finance
点击查看免费下载

导读

本文围绕 tf-quant-finance 中tf_quant_finance.experimental.lsm_algorithm模块展开,系统讲解基于 Longstaff & Schwartz(2001)回归法的最小二乘蒙特卡洛(LSM)美式期权定价实现:从 API 概览、least_square_mc与least_square_mc_v2两代定价入口的参数语义,到多项式基函数、篮子看跌期权 payoff 构造,再到与仓库源码、测试用例对照的算法原理纵深。读完本文,你将能够用该模块完成"模拟标的路径 → 构造 payoff 与基函数 → 回归求最优停时 → 折现均值"的完整美式期权定价流程,并理解 v2 版本为 XLA 兼容与批量估值所做的工程取舍。

模块定位与整体 API 结构

lsm_algorithm模块位于tf_quant_finance/experimental/下,模块 docstring 概括为"LSM algorithm methods"(LSM 算法方法集)。模块级索引文档 api_docs/tf_quant_finance/experimental/lsm_algorithm.md 列出了全部 5 个公开符号,定义于 tf_quant_finance/experimental/lsm_algorithm/init.py:

公开 API来源文件作用
least_square_mclsm.py用 LSM 算法为美式期权定价(基础版)
least_square_mc_v2lsm_v2.py用 LSM 算法为美式期权定价(XLA 兼容、支持 batch 与样本校准划分)
make_basket_put_payoffpayoff.py从样本构造简单篮子看跌期权的 payoff 可调用对象
make_polynomial_basislsm.py构造用于回归的多项式基函数(v1 版)
make_polynomial_basis_v2lsm_v2.py构造用于回归的多项式基函数(v2 版,带时间索引参数)

模块级导入后可通过tff.experimental.lsm_algorithm.least_square_mc等形式调用(tff.experimental.__init__.py第 20 行将lsm_algorithm纳入公开子模块)。在 Bazel 构建体系中,BUILD 将其拆分为lsm、lsm_v2、payoff三个py_library,并配套lsm_test、lsm_v2_test、payoff_test三个py_test目标。

LSM 算法原理回顾

least_square_mc的 docstring 对算法思想作了如下概括(与 lsm.py 一致):

最小二乘蒙特卡洛(LSM)算法是一种估值美式期权的蒙特卡洛方法。利用标的资产的样本路径和用户提供的 payoff 函数,它尝试为每条样本路径找到最优行权点;在已知最优行权点后,期权价值被定义为"假设最优行权"下的平均 payoff 并折现到现值。

这一思想源自文献:Longstaff, F.A. and Schwartz, E.S., 2001.Valuing American options by simulation: a simple least-squares approach. The review of financial studies, 14(1), pp.113–147。与普通蒙特卡洛只模拟到期 payoff 不同,美式期权允许在到期前的任意可行时点行权,因此核心难点在于估计每个时刻"继续持有"的期望价值(continuation value)。LSM 的巧妙之处在于:从后往前在每个可行行权时点,用该时点"实值路径"的样本做横截面回归(以当前标的价格的函数为解释变量,以未来已折现最优现金流为响应变量),得到条件期望函数的近似,再逐条路径比较"立即行权收益"与"继续持有期望",从而回溯出最优停时。

least_square_mc:基础版定价入口

函数签名与参数语义

tf_quant_finance.experimental.lsm_algorithm.least_square_mc( sample_paths, exercise_times, payoff_fn, basis_fn, discount_factors=None, dtype=None, name=None )

各参数含义(详见 least_square_mc.md):

  • sample_paths:形状为[num_samples, num_times, dim]的Tensor,即底层 Ito 过程在num_times个时间点上的dim维样本路径。
  • exercise_times:形状为[num_exercise_times]的int32Tensor,元素必须是[0, ..., num_times - 1]的子集,表示期权可行权的时点 tick。
  • payoff_fn:可调用对象,输入形状[num_samples, num_times, dim]的样本与一个表示当前时间索引的整数标量,输出形状[num_samples, payoff_dim]的Tensor(dtype 与样本一致),表示在该时点立即行权的支付。payoff_dim允许在同一标的资产(samples)上并行估值多个期权。
  • basis_fn:可调用对象,输入形状[num_samples, dim]的样本,输出形状[basis_size, num_samples]的Tensor,即用于回归持有价值的设计矩阵。
  • discount_factors:形状[num_exercise_times]或[num_samples, num_exercise_times]的Tensor,第 k 个元素表示时间 tick k 处的折现因子。默认None,映射为与样本同 dtype、形状[num_exercise_times]的全 1Tensor。
  • dtype:可选tf.float32或tf.float64,指定输入输出Tensor的 dtype;默认None时由 TensorFlow 推断。
  • name:Pythonstr,为函数创建的 Op 添加前缀;默认None映射为'least_square_mc'。

返回值:形状[num_samples, payoff_dim]、与samples同 dtype 的Tensor。

源码级执行流程

从 lsm.py 的实现可以看到以下关键步骤:

  1. 输入规整:sample_paths、exercise_times、discount_factors统一转为Tensor;若discount_factors缺省则构造全 1 折现向量;若其 rank 为 1,则扩展为[1, num_exercise_times](第 204-205 行),并在末尾concat一个值为 1 的前缀元素,使discount_factors[0] == 1代表 0 时刻的折现因子(第 207-209 行)。
  2. 现金流初始化:取最后一个可行权 tick,调用payoff_fn得到到期 payoff(形状[num_samples, payoff_dim]),并在其后拼接num_times - 1个 0,构成形状[num_samples, payoff_dim, num_exercise]的cashflow张量(第 212-221 行)。
  3. 倒推循环:通过tf.while_loop以LsmLoopVars(exercise_index, cashflow)为循环变量,从num_times - 1递减到 0(循环条件exercise_index > 0,见lsm_loop_cond第 236-239 行)。循环体_lsm_loop_body(第 354-380 行)每个迭代执行:
    • 计算当前 tick 的即时行权价值exercise_value = payoff_fn(sample_paths, tick);
    • 用continuation_value_fn将当前索引右侧的现金流折现到当前时点,得到"继续持有"的现值(第 242-269 行,折现比例由discount_factors[..., exercise_index + 1:] / discount_factors[..., exercise_index]给出);
    • 取sample_paths[:, tick, :]调用basis_fn构造回归设计矩阵;
    • 调用expected_exercise_fn做最小二乘回归,得到每条路径期望持有价值(详见下文);
    • 调用_updated_cashflow(第 318-351 行)更新现金流:当exercise_value > expected_continuation时判定该路径应提前行权,写入新的现金流并将之后的现金流置零。
  4. 定价输出:循环结束后用continuation_value_fn(loop_value.cashflow, discount_factors, 0)将现金流折现到 0 时刻,再对样本维度做reduce_mean(第 231-233 行),即得平均最优行权 payoff 的现值。

回归核心:expected_exercise_fn

回归的数学本质在 lsm.py 的注释中交代得很清楚:对于设计矩阵 X 与响应 y,最优线性无偏估计系数 β 满足正规方程X'X β = X'y。实现细节包括:

  • 仅在实值路径上回归:mask = cast(exercise_value > 0, ...)将非实值路径的设计矩阵行清零(第 297-300 行),因为"永远不会在该时点行权"的样本不影响回归系数;注释同时指出,同一组样本路径在不同 payoff 下实值集合不同,因此batch_design通过broadcast_to为每个 payoff 维复制一份设计矩阵。
  • 伪逆保证数值稳定:lhs = matmul(masked, masked, transpose_a=True)后用tf.linalg.pinv(lhs)计算伪逆(第 305-308 行),避免病态矩阵导致的数值不稳定。
  • 结果截断:最终返回tf.maximum(continuation, 0.0)(第 315 行),即期望持有价值不小于 0——这与"继续持有期权不会带来负的期望价值"的金融直觉一致。

论文示例的测试验证

lsm_test.py 直接复现了 Longstaff & Schwartz 论文 Section 1 的经典 8 条路径、3 个行权时刻算例:

samples = [[1.0, 1.09, 1.08, 1.34], [1.0, 1.16, 1.26, 1.54], [1.0, 1.22, 1.07, 1.03], [1.0, 0.93, 0.97, 0.92], [1.0, 1.11, 1.56, 1.52], [1.0, 0.76, 0.77, 0.90], [1.0, 0.92, 0.84, 1.01], [1.0, 0.88, 1.22, 1.34]] # 每两期之间的利率为 0.06,对应折现因子 interest_rates = [0.06, 0.06, 0.06] discount_factors = np.exp(-np.cumsum(interest_rates))

test_american_option_put(lsm_test.py)用make_polynomial_basis(2)与make_basket_put_payoff([1.1]),在exercise_times=[1, 2, 3]下得到美式看跌价格0.1144;test_european_option_put仅在exercise_times=[3]行权,得到欧式价格0.0564,与论文手算结果吻合。这组测试同时验证了算法在tf.float32/tf.float64两种精度下都稳定。

make_basket_put_payoff:篮子看跌 payoff 构造器

tf_quant_finance.experimental.lsm_algorithm.make_basket_put_payoff( strike_price, dtype=None, name=None )
  • strike_price:与样本 dtype 一致的Tensor,形状[num_samples, num_strikes],可同时为多个行权价构造 payoff。
  • dtype/name:语义同前,name默认'put_valuer'。
  • 返回:一个可调用对象,输入形状[num_samples, num_exercise_times, dim]的样本与当前时间标量,输出形状[num_samples, num_strikes]的 payoff。

底层实现在 payoff.py 的_put_valuer中:取出time_index处的切片样本,对最后一维(篮子成分维度dim)求平均average = reduce_mean(slice_sample_paths, axis=-1),再返回tf.nn.relu(strike_price - average),即篮子平均价格低于行权价的差额(不为负)。它通过functools.partial把strike_price绑定进闭包形成可调用对象。值得注意,该实现天然兼容 batch 输入:rank 为 3 时自动expand_dims到[num_samples, 1, num_times, dim],rank 为 4 时转置为[num_samples, batch_size, num_times, dim](第 79-84 行)。

payoff_test.py 给出了可直接对拍的手算期望:对 strike[1.1, 1.2]、末时刻样本,第 3 条路径(1.03)的 payoff 为[0.07, 0.17],第 4 条路径(0.92)为[0.18, 0.28],第 6 条路径(0.90)为[0.2, 0.3]等。

make_polynomial_basis:回归用的多项式基函数

tf_quant_finance.experimental.lsm_algorithm.make_polynomial_basis(degree)
  • degree:int32标量,期望的多项式次数;若小于 0,tf.debugging.assert_greater_equal会抛出断言(docstring 声明为ValueError,见 lsm.py)。
  • 返回:输入[num_samples, dim]、输出[degree * dim, num_samples]的可调用对象。

核心逻辑(lsm.py):先做中心化Y = X - mean(X, axis=0),再构造次数从 0 到degree的完整单项式网格并做reduce_prod,最后转置。docstring 中的示例(degree=2, dim=2)说明其展开包含1, X, X**2, Y, Y**2, X*Y, X**2*Y, X*Y**2等项。附带的数值示例:

basis = make_polynomial_basis(2) x = [1.0, 2.0, 3.0, 4.0] x = tf.expand_dims(x, -1) basis(x) # Expected result: # [[ 1.0, 1.0, 1.0, 1.0], [-1.5, -0.5, 0.5, 1.5]]

第一行是常数项 1,第二行是中心化后的X - mean(X)(均值为 2.5,故为-1.5, -0.5, 0.5, 1.5)。注意此处输出形状为[degree * dim, num_samples],与 v2 版本存在差异(见下)。

least_square_mc_v2:XLA 兼容的升级版

签名差异

tf_quant_finance.experimental.lsm_algorithm.least_square_mc_v2( sample_paths, exercise_times, payoff_fn, basis_fn, discount_factors=None, num_calibration_samples=None, dtype=None, name=None )

与 v1 相比,v2(lsm_v2.py)的核心变化体现在:

  1. 支持 batch 维度:sample_paths可为[num_samples, num_times, dim]或[batch_size, num_samples, num_times, dim],batch_size允许并行估值多个期权(通过 payoff 的"多个标的"或"多组样本路径"两种方式,见 lsm_v2_test.py 中test_american_option_put_batch_samples与test_american_option_put_batch_payoff)。相应地payoff_fn输出形状变为[num_samples, batch_size],basis_fn需接收完整样本路径与时间索引两个参数,输出[batch_size, basis_size, num_samples]。
  2. 新增num_calibration_samples:可选整数,不超过num_samples,指定用于 LSM 回归步骤的路径条数;注意定价时只用最后num_samples - num_calibration_samples条路径(第 284-286 行),即"回归用前 N 条、定价用后 M 条",以降低用同一批样本既做回归又做定价带来的偏差。默认None表示所有样本同时用于回归与定价。
  3. 静态形状与 XLA 兼容:文件头部 docstring(第 15-26 行)明确说明,v2 是为XLA 兼容而设计——_continuation_value_fn、_expected_exercise_fn、_updated_cashflow内部所有张量均为静态形状(用tf.where+ 固定形状掩码替代 v1 中的动态拼接),代价是内存占用上升,且"某些情况下可能比不做 XLA 编译的旧版慢"。make_polynomial_basis_v2输出的函数额外带time_index参数(内部用tf.slice按索引切片,避免动态形状张量),这也是它与 v1 基函数的主要区别。
  4. 折现因子 rank 3 支持:discount_factors可为[num_exercise_times]或与[num_samples, batch_size, num_exercise_times]兼容的 rank 3 张量(第 243-249 行用tf.pad前置 1)。
  5. 回归细节:_expected_exercise_fn(第 331-386 行)在 v1 的"实值掩码 + 伪逆"基础上增加calibration_indices的tf.gather子采样;输出用tf.nn.relu截断非负。

v2 的回归基函数:make_polynomial_basis_v2

tf_quant_finance.experimental.lsm_algorithm.make_polynomial_basis_v2(degree)

与 v1 的差异在于返回的可调用对象接收(sample_paths, time_index)两个参数:内部先按time_index切片出当前时点的样本,再中心化并做幂网格展开(lsm_v2.py)。输出形状为[batch_size, (degree + 1)**dim, num_samples]——注意 v2 是完整的(degree + 1)**dim个单项式(含所有交叉项与常数项),而 v1 docstring 写作[degree * dim, num_samples]并宣称展开含X*Y等交叉项,两者展开的项数规则并不相同,选用时需按形状断言核对。文档自带示例:

basis = tff.experimental.lsm_algorithm.make_polynomial_basis_v2(2) x = [[1.0], [2.0], [3.0], [4.0]] x = tf.expand_dims(x, axis=-1) basis(x, tf.constant(0, dtype=np.int32)) # Expected result: # [[ 1. , 1. , 1. , 1. ], [-1.5 , -0.5 , 0.5 , 1.5 ], # [ 2.25, 0.25, 0.25, 2.25]]

即[常数项 1, 中心化一次项 X-2.5, 中心化二次项 (X-2.5)**2]。

端到端实战:欧式/美式看跌期权定价对照

主文档least_square_mc与least_square_mc_v2均附有同一份完整示例(lsm.py、lsm_v2.py),下面给出修正笔误后的可运行版本(原文档中lsm_price(...)应为least_square_mc(...),strikes应为strike):

import numpy as np import tensorflow as tf import tf_quant_finance as tff from tf_quant_finance.experimental.lsm_algorithm import ( least_square_mc, make_basket_put_payoff, make_polynomial_basis) # 标的为 Black-Scholes 过程:dS_t / S_t = rate dt + sigma**2 dW_t,S_0 = 1.0 # 其中 rate = 0.1,波动率 sigma = 1.0。先定义 log(S_t) 的漂移与波动函数 rate = 0.1 def drift_fn(_, x): return rate - tf.ones_like(x) / 2. def vol_fn(_, x): return tf.expand_dims(tf.ones_like(x), -1) # 用 Euler 格式将 100000 条路径向前推进 1 年 times = np.linspace(0., 1, num=50) num_samples = 100000 log_paths = tf.function(tff.models.euler_sampling.sample)( dim=1, drift_fn=drift_fn, volatility_fn=vol_fn, random_type=tff.math.random.RandomType.PSEUDO_ANTITHETIC, times=times, num_samples=num_samples, seed=42, time_step=0.01) # 取指数还原 S_t 样本 paths = tf.math.exp(log_paths) # 行权价 1.1、期限 1 年的美式看跌期权 strike = [1.1] exercise_times = tf.range(times.shape[-1]) discount_factors = tf.exp(-rate * times) payoff_fn = make_basket_put_payoff(strike) basis_fn = make_polynomial_basis(10) american_price = least_square_mc(paths, exercise_times, payoff_fn, basis_fn, discount_factors=discount_factors) # 期望结果:约 [0.397] # 对照:同一标的的欧式看跌期权(仅到期行权) european_price = tff.black_scholes.option_price( volatilities=[1], strikes=strike, expiries=[1], spots=[1.], discount_factors=discount_factors[-1], is_call_options=False, dtype=tf.float64) # 期望结果:约 [0.379]

该示例要点:

  • 路径模拟复用 euler_sampling.sample,随机数采用PSEUDO_ANTITHETIC(对偶变量)降低方差,seed=42保证可复现;
  • 每条路径在 50 个时间点采样,exercise_times = tf.range(50)表示每个采样点都可行权;
  • 美式价格(约 0.397)高于欧式价格(约 0.379),差值即为"提前行权权利"的价值——这是检验 LSM 定价合理性的直观判据。

选型建议与注意事项

  1. v1 与 v2 的取舍:v2 是为 XLA 编译设计的静态形状实现(lsm_v2.py),更契合tf.function/ XLA 加速场景;v1 动态拼接在某些非 XLA 场景下可能更快、内存占用更低。若需并行估值多个期权或使用num_calibration_samples防过拟合,应选 v2。
  2. 基函数与 degree 选择:degree过小(如 1~2)回归精度不足,过大则设计矩阵膨胀、过拟合风险上升。论文示例与测试用degree=2即可在 8 条路径上精确复现;蒙特卡洛大样本场景常用 10 阶(主文档示例),但仍需结合标的维度权衡(degree+1)**dim的爆炸式增长。
  3. 仅实值路径参与回归:expected_exercise_fn用exercise_value > 0掩码(lsm.py),实值判定的直觉是"虚值路径在当期必不行权",这与 Longstaff-Schwartz 原始论文一致。
  4. dtype 一致性:discount_factors、strike_price需与sample_pathsdtype 一致;定价对精度敏感时建议显式传入tf.float64。
  5. 回归稳定性:实现使用tf.linalg.pinv伪逆求解正规方程(v1/v2 相同),对病态设计矩阵具有较好的容错性。

与稳定版models.longstaff_schwartz的关系

experimental.lsm_algorithm与 models/longstaff_schwartz 是同一算法在仓库中的两条演进线:稳定版tff.models.longstaff_schwartz提供了least_square_mc、make_polynomial_basis、make_basket_put_payoff三个同名 API,其签名(含num_calibration_samples与 batch 支持)与 experimental 下的 v2 版本一致,实现在 models/longstaff_schwartz/lsm.py 中。从源码结构看,experimental 版本更贴近算法原型与研究用途,稳定版则对类型标注、docstring 与 API 规范做了收尾。生产环境建议优先使用models.longstaff_schwartz,研究原型或需要对照两代实现差异时可参考experimental.lsm_algorithm的源码与测试(lsm_test.py、lsm_v2_test.py)。

  • 金融科技
  • 科学计算

【免费下载链接】tf-quant-finance

High-performance TensorFlow library for quantitative finance.

项目地址:https://gitcode.com/gh_mirrors/tf/tf-quant-finance
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

Android显示驱动底层路径图:从VSync信号链到MIPI屏适配

1. 这不是“学驱动”,而是重建你对Android显示系统的底层认知很多人看到“Android显示驱动”几个字,第一反应是:这得会写C、懂内核、看懂ARM汇编、熟悉DisplayPort协议……然后默默关掉页面。我完全理解——十年前我第一次打开drivers/gpu/ms…

作者头像 李华
网站建设 2026/10/12 13:59:17

RN适配OpenHarmony实战:字体、原生回调、包体与卡顿优化

1. 从“能跑”到“跑稳”——第五篇的状态与目标1.1 前四篇做过什么这个系列写到第五篇,其实挺超出我最初预期的。最开始我以为学习RN for OpenHarmony只是装个依赖、跑个demo的事,结果前四篇一路下来,环境配置、SDK匹配、Metro与原生工程握手…

作者头像 李华
网站建设 2026/10/12 13:59:06

舌苔识别系统毕设实战:从数据标注到GUI部署全链路

简介:本资源是一套面向计算机专业本科生的高分毕业设计实战项目,聚焦中医舌诊数字化落地,提供完整的基于深度学习的舌苔识别检测与鉴定系统实现方案。适用于毕设选题、课程设计及AI视觉项目练手,尤其适合零基础但具备Python基础的…

作者头像 李华
网站建设 2026/10/12 13:57:23

AI芯片软硬协同调试:72小时定位性能抖动与功耗异常

1. 项目概述:这不是芯片设计教科书,而是一份“踩过坑才敢写的实战手记”“AI 芯片的软硬件设计 3”这个标题乍看像课程编号,但在我过去十年参与多个边缘端AI加速器原型开发、流片验证和量产落地的过程中,它实际指向一个非常具体、…

作者头像 李华
网站建设 2026/10/12 13:56:18

C#批量PDF转Word工具:方案选型与排版保真实战解析

上个月朋友扔给我一个活儿:几百份PDF合同要转成Word,要求排版基本不变,能继续编辑。我第一批用在线工具转完就发现问题了,乱码、表格错位、图片丢失,客户根本没法用。后来我干脆用C#写了一个批量转换工具,前…

作者头像 李华
网站建设 2026/10/12 13:52:06

打造开放式代码审查流程:原理、落地与避坑指南

代码审查这事,我一直觉得是“人人都说重要,但推行起来全是坑”的典型。团队小的时候没什么感觉,一超过五个人,合代码就变成了一种玄学:要么靠吼,要么靠某一个资深同事半夜给人擦屁股。后来我主导推行了一套…

作者头像 李华