统一的证券标识符<trading_code>.<namespace>#
查询行情、财务或公司行动,首先要确定查询的是哪个对象。
libfinance 统一使用 <trading_code>.<namespace>,在 API 中称为
order_book_id:交易代码便于识别,命名空间消除同名歧义。
这套设计同时分开了三个问题:证券是谁、在哪里上市、数据覆盖哪些成交。
从代码冲突到命名空间#
单独的 000001 不够明确:它既可以指上证综合指数,也可以指平安银行。
补上命名空间,才能确定对象。类型则由证券元数据中的 type 表达:
order_book_id |
对象 |
type |
|---|---|---|
|
上证综合指数 |
|
|
平安银行 |
|
|
浦发银行 |
|
|
沪深300 |
|
XSHG 并不表示指数,XSHE 也不表示股票。
同一个命名空间可以包含不同类型的对象;完整代码用于查找对象,
type 用于判断应如何处理它。行情接口也据此区分股票行情与指数行情,
不靠代码前几位猜测类型。
XSHG、XSHE 的标准来源#
这两个后缀取自 ISO 10383 的市场标识码
(Market Identifier Code,简称 MIC)。MIC 是四位字母或数字组成的标准代码;
登记表将 XSHG 分配给上海证券交易所,将 XSHE 分配给深圳证券交易所。
它们不是本库自造的英文缩写,也不编码证券类型。
可查阅 ISO 的 MIC 登记表。
美股后缀 US 则取自
ISO 3166-1 的两字母国家代码。
本库选择命名空间的原则是:代码在哪个范围内能够消除歧义,就使用哪个范围。
沪深代码空间存在重叠,需要区分交易所;美国上市股票有跨交易所协调的代码体系,
使用全国代码空间即可。统一的是格式与含义,命名空间的粒度由市场实际机制决定。
000300:指数标识不等于股票标识#
000300.XSHG 在本库中表示沪深300指数。
上交所公布的编制方法明确:该指数在上海行情中使用 000300,
在深圳行情中使用 399300,并从沪深市场选取成份股。
因此,后缀 XSHG 既不表示它是一只上海股票,也不表示它只包含沪市股票。
见 沪深300指数编制方法。
指数的命名空间用于定位发布或行情代码体系中的对象,不表示指数有自己的撮合订单簿。
跟踪沪深300的 ETF、指数成份股以及指数本身,也是不同对象,各有自己的代码。
不能仿照 000001 的例子,把 000300 换成 .XSHE 就认定存在同代码股票;
代码是否存在、是什么类型,应查询证券目录。
import libfinance as lf
for item in lf.instruments([
"000001.XSHE", "000001.XSHG", "600000.XSHG", "000300.XSHG"
]):
print(item.order_book_id, item.symbol, item.type)
示意输出(名称以服务端数据为准):
000001.XSHE 平安银行 CS
000001.XSHG 上证指数 INDX
600000.XSHG 浦发银行 CS
000300.XSHG 沪深300 INDX
也可以直接核对目录中所有以 000300 为交易代码的记录,避免自行补全后缀:
catalog = lf.all_instruments(market="cn")
matched = catalog[
catalog["order_book_id"].str.split(".", regex=False).str[0] == "000300"
]
print(matched[["order_book_id", "symbol", "type"]].to_string(index=False))
美股为什么使用 US#
理解这一选择,需要把上市、交易和行情汇总分开。
概念 |
回答的问题 |
对标识设计的影响 |
|---|---|---|
上市地(listing venue) |
证券在哪家交易所挂牌、遵守其上市规则? |
是证券的上市属性,可以变化 |
交易场所(trading venue) |
这笔订单实际在哪里成交? |
同一证券可以在多个场所成交 |
合并行情(consolidated tape) |
各场所报送的成交、报价汇总后是什么情况? |
描述数据覆盖范围,不是另一只证券 |
代码分配跨交易所协调。 美国的 NMS 证券代码选择与预约计划, 通过跨市场的 ISRA 机制协调代码使用,避免各家交易所独立分配相互冲突的根代码。 因此,美国上市股票的 ticker 不必再附带上市所才能定位。 这不意味着所有资产类别、所有历史时点都能只靠一个 ticker 区分。 见 Nasdaq 代码预约说明。
挂牌不意味着只能在该所成交。 一只在 Nasdaq 挂牌的股票, 订单也可以被送往其他交易所、做市商或电子交易网络。 仅统计某一家场所的成交,不能当作该股票的全市场成交。 见 SEC:股票买卖的交易场所。
合并行情负责汇总。 SIP(证券信息处理器)汇集参与市场报送的成交与报价。 常见的 CTA Tape A/B 与 UTP Tape C 按上市证券分组组织行情, 并非只收录对应上市所发生的成交。可参阅 CTA 与 UTP 的机制说明。 合并成交价、单一场所成交价和上市所官方收盘价,也可能是不同口径。
因此,AAPL.US 表示美国代码空间中的苹果股票;
上市地可以单独记录为 XNAS,实际成交场所则可能有多个。
US 不承诺某个数据源已经覆盖全部场所,行情覆盖范围仍需查看产品说明。
如果股票转板但 ticker 不变,采用 .US 也能避免仅因上市所变化而改写标识。
从标识到跨市场查询#
完整代码提供了市场路由所需的信息,按证券查询时不必再传 market。
服务端可以分别查询混合列表中的市场,再合并结果,避免调用方手工拆分,
也避免出现“代码指向美国、market 却指定中国”的冲突。
for item in lf.instruments(["000001.XSHE", "AAPL.US"]):
print(item.order_book_id, item.symbol, item.type)
交易日历、全市场目录等查询没有指定单只证券,仍保留 market 来选择范围;
例如 all_instruments 省略它时,会合并服务端已绑定市场。
能够识别命名空间也不等于对应市场或数据集一定已接入。
规范化与扩展:避免另一种歧义#
上游设计还约定了以下机制,让代码形式保持可解析:
代码内部的标点归一化为连字符,例如
BRK.A写成BRK-A.US, 避免把股票类别中的点误读为命名空间分隔符。在需要进一步消歧的品种上,格式可扩展为
<trading_code>.<namespace>.<class>,例如设计中的IBM.US.PR-A。 第三段是可选扩展,不是现有股票和指数都必须添加的类型标签。不同来源的别名应先解析到统一代码,输出保持一致; 无法唯一解析时应拒绝猜测,不能默认选中某个市场或对象。
这些是标识规范的设计约定,不代表客户端已开放全部扩展品种或别名解析。
当前调用应使用证券目录返回的完整 order_book_id。
同样,原设计中用于表达行情范围的 venue、meta.scope 等接口示意,
不构成当前 get_price 的参数或返回承诺。
可读代码与永久身份#
命名空间解决同一时点的冲突,历史上的更名和代码复用还需要另一层机制。 上游将身份分为:
层次 |
作用 |
|---|---|
|
永久证券身份,不随名称、代码或上市所变化而重建 |
|
在某个 MIC 上的一段连续上市关系 |
代码及有效期 |
记录该证券在什么时间使用哪个可读代码 |
外部标识映射 |
保存 ISIN、FIGI 等外部标识及其有效期,连接不同数据来源 |
例如同一证券从 FB.US 改名为 META.US,永久身份应保持不变;
若旧代码后来分配给另一只证券,则必须区分身份,不能把两段行情直接拼接。
永久身份与上市关系只存在于服务端,不出现在任何返回结果中:客户端始终以 order_book_id 标识证券,
历史上的身份由 as_of 解析——instruments(..., as_of=...) 查看某日有效的证券信息,
按代码查询的函数在服务端完成代码到身份的对应。
另一个容易混淆的层次是公司与证券:同一公司的普通股、ADR 或不同股份类别,
可以是不同证券。证券价格属于具体证券,财务报表则需要关联到报告主体。
“同一家公司”不意味着这些证券应合用一个 order_book_id。