gs-quant HistoricalPricingContext 实战指南:多日期历史估值与风险计算
2026/9/15 12:10:19 网站建设 项目流程

gs-quant HistoricalPricingContext 实战指南:多日期历史估值与风险计算

【免费下载链接】gs-quantPython toolkit for quantitative finance项目地址: https://gitcode.com/GitHub_Trending/gs/gs-quant

本指南以 gs-quant 仓库中 HistoricalPricingContext 类文档 为核心,系统讲解如何在一次上下文中对同一金融工具批量计算多个历史日期的估值与风险度量。读完本文,你将掌握HistoricalPricingContext的完整参数语义、start/end/dates三种日期构造方式、同步与异步执行模式,以及其派生类BackToTheFuturePricingContext的前瞻估值能力,并能在真实交易分析、回测与研报复盘中直接落地使用。

一、什么是 HistoricalPricingContext

在 gs-quant 中,PricingContext(gs_quant/markets/core.py)负责控制定价与市场数据行为:定价日期、市场数据来源地(NYC/LDN/HKG)、异步或批处理模式、缓存策略等。而HistoricalPricingContext是它的一个直接子类,定位非常明确——“A context for producing valuations over multiple dates”(用于在多个日期上产生估值的上下文),源码位于 gs_quant/markets/historical.py。

它的核心价值在于:传统PricingContext只针对单一pricing_date计算,而历史分析(如回测收益、历史波动率归因、逐日 delta 对冲)需要同一笔交易在几十甚至上百个历史日期上逐一估值。HistoricalPricingContext把“构造日期序列 → 逐日构建风险请求 → 汇总成一条结果序列”封装成一个可复用的with上下文。

从继承关系看,它调用了父类构造器并强制设置use_historical_diddles_only=True(仅使用历史市场数据点),并将自己构造出的日期序列保存在内部属性__date_range中(historical.py)。

二、构造参数详解:日期、执行模式与数据来源

HistoricalPricingContext.__init__的完整签名如下(见 historical.py):

HistoricalPricingContext( start=None, # 起始日期,或“end 之前的业务日数量”(int) end=None, # 结束日期,默认为今天 calendars=(), # 节假日日历 dates=None, # 自定义日期可迭代对象 is_async=None, # True 立即返回 future,False 阻塞等待(默认 False) is_batch=None, # 预计运行超过 3 分钟时使用,避免超时 use_cache=None, # 是否把结果存入定价缓存(默认 False) visible_to_gs=None, # 风险请求内容是否对 GS 可见(默认 False) request_priority=None, # 风险请求的优先级 csa_term=None, # 计算所用的 CSA 条款,默认本地货币 OIS 指数 market_data_location=None, # 市场数据来源地:'NYC'、'LDN' 或 'HKG'(默认 LDN) timeout=None, # 批处理操作超时时间 show_progress=None, # 是否显示 tqdm 进度条 use_server_cache=None, # 是否在 GS 服务器端缓存查询结果 provider=None, # 用于定价请求的 GenericRiskApi 实现 )

1. 日期参数的三种用法(start/end/dates)

源码中日期解析逻辑位于 historical.py,规则如下:

  • 提供start(且不提供dates:与end配合生成日期序列。若end缺省则默认为今天;start可以是datetime.date,也可以是int(此时表示“end之前 N 个业务日”)。序列通过gs_quant.datetime.date.date_range(start, end, calendars=calendars)生成(date_range 实现),自动排除节假日。
  • 提供dates(且不提供start:直接使用你给定的任意日期可迭代对象,适合回测引擎传入自定义状态日期(如 generic_engine.py 中with HistoricalPricingContext(dates=p.dates)的用法)。
  • 同时提供startdates:抛出ValueError('Must supply start or dates, not both')
  • 两者都不提供:抛出ValueError('Must supply start or dates')

2. 执行模式与性能相关参数

参数默认值作用
is_asyncFalseTrue 时立即返回 future,适合并行提交大量任务
is_batchFalse用于预计运行超过 3 分钟的计算,避免请求超时;可与is_async任意组合
use_cacheFalse将结果写入本地定价缓存(PricingCache,弱引用字典,见 core.py),相同 RiskKey 的重复计算直接命中缓存
use_server_cacheFalse在 GS 服务器端缓存查询结果
timeout批处理操作的超时秒数
show_progressFalse显示 tqdm 进度条
request_priority风险请求优先级

3. 市场与数据相关参数

  • market_data_location:市场数据来源地,可选'NYC''LDN''HKG',默认LDN。该值同时决定了收盘市场日期的计算(见CloseMarketroll_hr_and_minclose_market_date,markets.py)。
  • csa_term:计算所用 CSA(信用支持附件)条款,默认取本地货币 OIS 指数。
  • visible_to_gs:风险请求内容是否对 GS 可见,默认False
  • providerGenericRiskApi实现,默认使用instrument.provider(见 historical.py)。

父类PricingContext还支持marketMarket对象)、market_behaviour(曲线构建行为,'ContraintsBased''Calibrated',默认前者)、set_parameters_only等参数(core.py),这些同样可以被HistoricalPricingContext继承使用。注意:父类会在pricing_date超过今天 5 天以上时抛出ValueError,提示改用RollFwd场景来处理未来日期(core.py)。

三、快速上手:历史价格序列计算

以官方文档示例为基础,计算一只 DKK 利率互换在过去 10 个业务日的价格序列:

from gs_quant.instrument import IRSwap from gs_quant.markets import HistoricalPricingContext ir_swap = IRSwap('Pay', '10y', 'DKK') with HistoricalPricingContext(10): # 10 = 截至今天的 10 个业务日 price_f = ir_swap.price() # 在每个历史日期上提交价格计算 price_series = price_f.result() # 阻塞等待,返回序列结果

更一般地,可同时计算多个风险度量。例如计算过去 150 个业务日的价格(对应官方教程 06_calc_swap_price_historically.ipynb 中的用法):

import datetime as dt from gs_quant.markets import HistoricalPricingContext with HistoricalPricingContext(150): # 150 个业务日 price_f = swap.price() price_history = price_f.result() # 一条覆盖 150 个日期的序列

也支持显式日期区间与自定义日期列表:

with HistoricalPricingContext(dt.date(2025, 3, 25), dt.date(2025, 3, 27)): price_f = swap.price() with HistoricalPricingContext(dates=[dt.date(2025, 3, 25), dt.date(2025, 3, 26), dt.date(2025, 3, 27)]): price_f = swap.price()

在长区间上推荐开启进度条与批处理:

with HistoricalPricingContext(start=start_date, end=end_date, is_batch=True, csa_term='EUR-OIS'): price_f = swap.price()

其中is_batch=True配合自定义csa_term正是仓库内容示例 inflation_covid19_recovery_trade.ipynb 中的真实用法。

四、逐日估值的工作机制:从日期到 RiskKey

理解HistoricalPricingContext的关键在于其calc实现(historical.py):

def calc(self, instrument, risk_measure): futures = [] provider = instrument.provider if self.provider is None else self.provider scenario = self._scenario parameters = self._parameters location = self.market.location for date in self.__date_range: risk_key = RiskKey(provider, date, self._market(date, location), parameters, scenario, risk_measure) futures.append(self._calc(instrument, risk_key)) return HistoricalPricingFuture(futures)

工作流程可以概括为四步:

  1. 确定 provider:未显式指定provider时使用instrument.provider
  2. 逐日构造RiskKey:每个历史日期对应一个RiskKey(provider, date, market, parameters, scenario, risk_measure),其中市场对象由_market(date, location)生成——即带日期的CloseMarket(historical.py),确保每个日期取用当日收盘市场数据;
  3. 批量提交计算:通过self._calc(instrument, risk_key)将每个日期的风险请求提交到活动上下文(父类_calc实现见 core.py,会先查询PricingCache缓存,命中则直接返回结果,避免重复计算);
  4. 返回聚合 future:所有单日 future 被打包进HistoricalPricingFuture

结果聚合:HistoricalPricingFuture

HistoricalPricingFuture定义于 gs_quant/risk/results.py,它在_set_result中取出每个单日结果,剔除ErrorValue/异常后,将多个日期的结果组合(compose)成一条序列结果;若全部日期均失败,则记录错误日志并把首个错误结果返回。因此price_f.result()拿到的是一个覆盖全部日期的复合结果(FloatWithInfo/DataFrameWithInfo等),而不是单个数值。

在回测引擎中的实际应用

HistoricalPricingContext是 gs-quant 回测框架的核心基础设施之一。在 generic_engine.py 中,回测引擎针对每个交易路径的日期状态直接构造HistoricalPricingContext(dates=...)来批量计算组合风险:

with HistoricalPricingContext(dates=p.dates): backtest.calculations += len(risks) * len(p.dates) port = p.trade if isinstance(p.trade, Portfolio) else Portfolio([p.trade]) p.results = port.calc(tuple(risks))

同样地,generic_engine_action_impls.py 中也会用HistoricalPricingContext(dates=states, csa_term=...)来推进路径依赖计算。这说明:凡需要“同一批工具在一串日期上逐日估值”的场景,都可以直接用该上下文完成

五、进阶:BackToTheFuturePricingContext 与前瞻估值

BackToTheFuturePricingContextHistoricalPricingContext的直接子类(historical.py),在历史估值之上叠加了面向未来日期的估值能力,适用于“今天模拟未来某天交易会如何定价”这类前瞻分析。

新增参数 roll_to_fwds

  • roll_to_fwds=True(默认):对晚于pricing_date的未来日期,假设远期曲线实现(fwd curve is realised),即市场沿着远期曲线演化;
  • roll_to_fwds=False:假设即期利率实现(spot rates are realised)

calc逻辑(historical.py)对日期序列做了分支处理:

  • 过去或当前日期date <= pricing_date):与HistoricalPricingContext一致,使用该日期的CloseMarket和基础场景;
  • 未来日期date > pricing_date):构造MarketDataScenario(RollFwd(date=date, realise_fwd=self._roll_to_fwds, name=self.name))RollFwd定义见 target/common.py),复用当前市场对象,将定价日期滚动到未来。

官方示例(假设今天在 2020-07-06 与 2020-07-14 之间):

import datetime as dt from gs_quant.instrument import IRSwap from gs_quant.markets import BackToTheFuturePricingContext ir_swap = IRSwap('Pay', '10y', 'DKK') with BackToTheFuturePricingContext(dt.date(2020, 7, 6), dt.date(2020, 7, 14), roll_to_fwds=True): price_f = ir_swap.price() price_series = price_f.result()

它在仓库中的真实用途可见于内容示例 00_us_election_analysis/0003_trades.ipynb(with BackToTheFuturePricingContext(dates=dates, roll_to_fwds=True)),以及 11-FX Election Hedge.ipynb 中对“BackToTheFuturePricingContext=HistoricalPricingContext+RollFwd”的说明。

六、常用属性速查

HistoricalPricingContext继承自PricingContext,以下属性均可直接访问:

属性含义
date_range本上下文覆盖的日期元组(自定义实现,见 historical.py)
pricing_date定价日期,默认按market_data_location的今日业务日(core.py)
market当前市场对象,默认按定价日期与市场位置构建CloseMarket(core.py)
market_data_location市场数据来源地,默认LDN(core.py)
is_async/is_batch异步模式 / 批处理模式
use_cache是否使用定价缓存(默认 False)
use_server_cache是否使用服务器端缓存
visible_to_gs请求内容是否对 GS 可见
csa_term计算所用 CSA 条款
request_priority风险请求优先级
timeout批处理超时
show_progress是否显示进度条
use_historical_diddles_only是否仅使用历史市场数据点(本类构造时强制为 True)
set_parameters_only置 True 时不阻止内嵌定价上下文提交任务
active_context/is_current/is_entered上下文生命周期状态:当前活动上下文、是否当前、是否已进入
clone/default_value克隆上下文 / 默认值(来自ContextBaseWithDefault

上下文还支持clone()复制,以及通过PricingContext.current修改默认上下文(如PricingContext.current = PricingContext(market_data_location='LDN'),见 core.py)。

七、典型应用场景与最佳实践

场景一:逐日滚动对冲模拟

仓库示例 3-Systematic Selling.ipynb 与 4-Delta Hedging.ipynb 展示了典型用法:外层用一个覆盖整段历史区间的大HistoricalPricingContext(start=start_date, end=end_date, show_progress=True)批量计算持仓风险,内层再对每个交易日在更窄的窗口上嵌套计算。

场景二:历史波动率与曲线形态分析

12-Structuring for Uncertaintly.ipynb 指出:在HistoricalPricingContext不调用resolve()的期权,会在序列中的每一天自动重新确定行权价(re-strike),从而得到每日都是 1.5% OTMS 的期权成本历史——这是做波动率结构分析的常用技巧。

最佳实践小结

  1. 明确日期语义start为 int 时表示业务日数量,为date时表示日期;二者不可与dates混用。
  2. 长区间开启批处理:预计单次计算超过 3 分钟时务必设置is_batch=True,避免请求超时。
  3. 异步提交、统一取回is_async=True可立即拿到 future,适合在回测中批量提交后再统一result()
  4. 善用缓存use_cache=True可让重复的 RiskKey 直接命中PricingCache,显著减少重复请求。
  5. 未来日期请用 RollFwd 语义:需要前瞻估值时使用BackToTheFuturePricingContext,而非直接设置未来pricing_date(父类会拒绝超过今天 5 天以上的定价日期)。

八、参考文件索引

  • 类文档:docs/classes/gs_quant.markets.historical.HistoricalPricingContext.rst
  • 核心实现:gs_quant/markets/historical.py(含HistoricalPricingContextBackToTheFuturePricingContext
  • 父类实现:gs_quant/markets/core.py(PricingContextPricingCache
  • 结果聚合:gs_quant/risk/results.py(HistoricalPricingFuture
  • 日期生成:gs_quant/datetime/date.py(date_range
  • 市场对象:gs_quant/markets/markets.py(CloseMarket
  • 场景对象:gs_quant/target/common.py(RollFwd
  • 回测集成:gs_quant/backtests/generic_engine.py、gs_quant/backtests/generic_engine_action_impls.py
  • 官方教程:06_calc_swap_price_historically.ipynb、05_resolve-a-trade.ipynb
  • 实战示例:3-Systematic Selling.ipynb、4-Delta Hedging.ipynb、inflation_covid19_recovery_trade.ipynb、00_us_election_analysis/0003_trades.ipynb

【免费下载链接】gs-quantPython toolkit for quantitative finance项目地址: https://gitcode.com/GitHub_Trending/gs/gs-quant

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询