首页
/ 掌握 gs-quant 的 Index.get_identifier:跨时间获取指数证券标识符的权威指南

掌握 gs-quant 的 Index.get_identifier:跨时间获取指数证券标识符的权威指南

2026-09-14 14:04:13作者:袁立春Spencer

导读

在 Goldman Sachs 开源的 Python 量化工具包 gs-quant 中,Index.get_identifier() 是查询指数(Index)证券各类市场标识符(如 RIC、Bloomberg ID、CUSIP、ISIN、SEDOL、Ticker)的统一入口。本文以 docs/functions/gs_quant.markets.index.Index.get_identifier.rst 所对应的 API 文档为核心,结合仓库源码与测试用例,系统讲解该方法的参数语义、时序(as-of)标识符解析机制、底层数据来源与缓存策略,并给出可直接运行的实战示例。读完本文,你将能够根据业务需要,在任意历史时点准确取回指数在各大数据体系中的标识符,并理解其在 gs-quant 证券主数据架构中的位置。

一、方法定位:Index 从何处继承 get_identifier

Index 类定义于 gs_quant/markets/index.py,其声明为:

class Index(Asset, PositionedEntity):

它同时继承自 Asset(资产基类)与 PositionedEntity(持仓实体),因此 Index.get_identifier() 并非 Index 自身定义的方法,而是继承自基类 Assetgs_quant/markets/securities.py 中实现的方法。docs 目录下的 gs_quant.markets.index.Index.get_identifier.rst 正是通过 Sphinx automethod 指令自动生成该方法的参考文档,其完整签名如下:

def get_identifier(self, id_type: AssetIdentifier, as_of: dt.date = None):

方法返回单个标识符值(字符串或 None),与一次性返回全部标识符字典的 get_identifiers(as_of=None)securities.py)形成互补关系。

二、参数详解:id_type 与 as_of

2.1 id_type:目标标识符类型

id_type 是枚举 AssetIdentifier 的实例,定义于 gs_quant/markets/securities.py。该枚举覆盖了主流证券标识体系,各成员及其取值如下:

枚举成员 取值 说明 示例
AssetIdentifier.MARQUEE_ID "MQID" Goldman Sachs Marquee 内部标识符 MA4B66MW5E27UAHKG34
AssetIdentifier.REUTERS_ID "RIC" 路透/Refinitiv 代码 GS.N
AssetIdentifier.BLOOMBERG_ID "BBID" 彭博标识符加交易所代码 GS UN
AssetIdentifier.BLOOMBERG_COMPOSITE_ID "BCID" 彭博综合标识符 GS US
AssetIdentifier.CUSIP "CUSIP" 美国证券统一识别编号委员会代码 38141G104
AssetIdentifier.ISIN "ISIN" 国际证券识别编码 US38141G1040
AssetIdentifier.SEDOL "SEDOL" 伦敦证券交易所每日官方列表代码 2407966
AssetIdentifier.TICKER "TICKER" 交易所代码 GS
AssetIdentifier.PLOT_ID "PLOT_ID" Marquee PlotTool 使用的 ID
AssetIdentifier.GSID "GSID" 高盛证券主数据内部 ID
AssetIdentifier.NAME "NAME" 资产名称 US Treasury 20y GOVN

2.2 as_of:标识符的有效日期

as_of 参数用于处理时序性标识符——证券(包括指数)的标识符可能随公司行动(如更名、换交易所、结构调整)而随时间变化。当传入 as_of 时,方法返回该日期在有效区间内的标识符;当省略时,则回退到当前 PricingContext 的定价日期(见下文源码剖析)。

三、官方文档示例:三种典型调用方式

Asset.get_identifier 的 docstring(securities.py)给出了三类官方示例,全部适用于 Index 实例:

3.1 获取当前 SEDOL

import datetime as dt
from gs_quant.markets.index import Index
from gs_quant.markets.securities import AssetIdentifier

# 先通过任意常见标识符解析出 Index 对象(如 Marquee 指数代码)
index = Index.get("GSMBXXXX")

# 获取当前 SEDOL
index.get_identifier(AssetIdentifier.SEDOL)

3.2 指定历史日期获取 SEDOL

index.get_identifier(AssetIdentifier.SEDOL, as_of=dt.date(2018, 1, 1))

3.3 借助 PricingContext 隐式指定 as-of 日期

from gs_quant.markets import PricingContext

with PricingContext(dt.date(2018, 1, 1)) as ctx:
    index.get_identifier(AssetIdentifier.SEDOL)

在第三种写法中,PricingContext 为上下文内的所有查询统一设定定价日期,as_of 将自动取自 ctxpricing_date,适合在同一个历史场景下批量查询多个指标时的场景一致性。

四、源码级原理剖析

4.1 两层调用链与 xref 时间过滤

get_identifier 的核心逻辑(securities.py)只有两步:

if id_type == AssetIdentifier.MARQUEE_ID:
    return self.get_marquee_id()

ids = self.get_identifiers(as_of=as_of)
return ids.get(id_type.value)
  • 特判分支MARQUEE_ID 无需网络查询,直接由 get_marquee_id() 返回对象内部的 Marquee ID(Index 在构造时即以 id_ 保存该值,见 index.py)。
  • 通用分支:委托给 get_identifiers(as_of),其实现(securities.py)通过 GsAssetApi.get_asset_xrefs(self.get_marquee_id()) 从 Marquee 拉取该资产的交叉引用(xref)记录;每条 xref 携带 startDateendDate,代码以 start_date <= as_of <= end_date 过滤出命中区间的记录,再将其 identifiers 字典按键名(大写后与 AssetIdentifier 取值比对)筛选后返回。

由此可以推断:标识符的时间有效性由服务端 xref 记录维护,客户端仅负责按 as_of 选取区间。

4.2 默认 as_of 的解析逻辑

省略 as_of 时(securities.py),方法读取 PricingContext.current.pricing_date;若当前上下文尚未进入(is_entered 为 False),则会自动 with current: 进入一次以获取定价日期。返回的 pricing_date 可能是 dt.datetime,此时会被统一转换为 dt.date 后再做区间比较。

4.3 结果缓存策略

get_identifier 上标注了 cachetools.cached 装饰器(securities.py):

@cachetools.cached(
    cachetools.TTLCache(256, 600),
    lambda s, id_type, as_of=None: cachetools.keys.hashkey(s.get_marquee_id(), id_type, as_of),
    threading.RLock(),
)

即:以 (marquee_id, id_type, as_of) 为键缓存,缓存容量 256 条、TTL 600 秒(10 分钟),并在多线程访问时以 RLock 保证线程安全。重复查询同一标识符不会重复发起网络请求,适合在循环中批量解析指数标识符的场景。

五、相关变体:SecMasterAsset 的 get_identifier

值得说明的是,gs_quant/markets/securities.pySecMasterAsset 重写了 get_identifier,其签名扩展为 Union[AssetIdentifier, SecurityIdentifier]

  • 传入 AssetIdentifier 时,会先经 _ASSET_TO_SECURITY_IDENTIFIER 映射转换为对应的 SecurityIdentifier(如 BLOOMBERG_ID → BBIDREUTERS_ID → RICTICKER → TICKERISIN → ISIN);
  • 若无对应等价映射(如 AssetIdentifier.PLOT_ID),则抛出 MqTypeError
  • 传入普通字符串则直接抛出 MqTypeError——id_type 必须是枚举成员,而非字符串字面量

该行为已由 gs_quant/test/markets/test_securities.py 中的 test_secmaster_asset_get_identifier_with_security_identifiertest_secmaster_asset_get_identifier_with_asset_identifiertest_secmaster_asset_get_identifier_unsupported_asset_identifier_raises 等用例验证。

六、测试佐证:真实标识符查询行为

仓库测试 gs_quant/test/markets/test_securities.py 展示了携带 as_of=dt.date.today() 的查询断言:

assert asset.get_identifier(AssetIdentifier.REUTERS_ID, as_of=dt.date.today()) == '.GSTHHVIP'
assert asset.get_identifier(AssetIdentifier.BLOOMBERG_ID, as_of=dt.date.today()) == 'GSTHHVIP'
assert asset.get_identifier(AssetIdentifier.CUSIP, as_of=dt.date.today()) == '9EQ24FPE5'
assert asset.get_identifier(AssetIdentifier.TICKER, as_of=dt.date.today()) == 'GSTHHVIP'

这些断言说明:同一资产在同一天内可同时返回多套标识体系的值,验证了 get_identifier 针对不同 id_type 的取值路径相互独立,也印证了 get_identifiers 一次性返回全部可用标识符后按需取值的实现方式。

七、使用注意事项与最佳实践

  1. 优先使用枚举而非字符串id_type 必须为 AssetIdentifier 枚举成员,传入 "SEDOL" 之类的裸字符串不会生效(对 SecMasterAsset 会直接抛 MqTypeError)。
  2. 利用缓存避免重复请求:方法自带 10 分钟 TTL 缓存,短时间内的重复查询开销极低;但对不同 as_of 的查询会各自成键,历史回溯时应尽量减少 as_of 取值数量。
  3. 保持历史查询的场景一致:涉及多个指标的历史查询,建议统一放入同一个 PricingContext,避免各自省略 as_of 而取到不同定价日期。
  4. 理解标识符的时效性:返回结果依赖服务端 xref 记录的有效区间;若资产在目标日期尚不存在,可能返回 None,业务侧应做好空值处理。
  5. 区分数据来源Index(继承自 Asset)与 SecMasterAsset 底层数据来源不同(前者走 GsAssetApi.get_asset_xrefs,后者走 SecurityMaster 的标识符历史),在需要与证券主数据对齐时,可结合 SecurityMasterSecMasterContext 使用对应变体。

结语

Index.get_identifier() 虽是一个签名简洁的 API,背后却串联了 gs-quant 的枚举体系、时序标识符数据模型、PricingContext 日期上下文与本地缓存机制。理解其继承关系(Index → Asset)与 as_of 语义,是正确构建跨市场、跨历史时点指数研究工作流的关键一步。相关参考文档位于 docs/functions/gs_quant.markets.index.Index.get_identifier.rst,完整实现与测试可分别查阅 gs_quant/markets/securities.pygs_quant/test/markets/test_securities.py

登录后查看全文
热门项目推荐
相关项目推荐