代码符号规整 — 跨场所去重分组
Canonical Ticker-Symbol Form — Cross-Venue Dedup
开始编码行情数据归一化器从多个上游源拿到原始代码字符串——不同供应商把 Apple 的代码写成 aapl、AAPL、AAPL.US、 aapl 等等,而想跨场所去重持仓的台桌需要这些写法在做任何 join、group-by 或查表之前先全部归并到唯一的 规整形式(canonical form)。
实现 solution(symbols, known_venue_suffixes) -> dict[str, list[str]]。对每个原始符号按以下顺序产出规整形式:(1) strip() 去掉首尾空白;(2) 把内部连续空白压成单空格(' '.join(s.split()));(3) upper();(4) 若结果以 '.' + sfx.upper() 结尾(其中 sfx 取自 known_venue_suffixes,大小写不敏感匹配),剥掉第一个满足条件的后缀。把原始符号按规整形式分组,组内保留 原始符号(不是规整形式),并保持 输入顺序。返回该 dict。
举例:solution(["aapl", "AAPL.US", " aapl ", "AAPL"], ["HK", "US", "LSE"]) 返回 {"AAPL": ["aapl", "AAPL.US", " aapl ", "AAPL"]}——四种写法都规整到 "AAPL"。没有匹配上已知场所后缀的符号保留其完整大写形式作为键(例如 "MSFT.US" 配后缀表 ["HK"] 仍然是 "MSFT.US")。strip 后为空字符串则映射到规整键 ""。
实践背景
跨场所代码去重是几乎每个量化台桌在做 join 之前都要跑的最小数据洁净化。同一个标的会在多个场所交易,带不同的场所后缀——0700.HK(腾讯,港股)、AAPL.US(苹果,美股)、VOD.LSE(沃达丰,伦敦)——而不同供应商给出的代码列在大小写、空白、是否带后缀这些细节上往往不一致。不做规整就直接 join,会导致持仓重复计数、风险敞口漏算、PnL 归因悄悄跑偏。生产代码通常把这套归一化封装成一个工具函数,因为下游每条流水线都要用:持仓汇总、因子模型对齐、公司行为对齐、行情回填都跑同一份。known_venue_suffixes 上的"先匹配优先"规则让运维方在多个场所后缀字典冲突时表达优先级,而无需改造归一化器本身。
约束条件
- 1 ≤ `len(symbols)` ≤ 10000
- 对每个 `symbols` 中的 `symbol`,0 ≤ `len(symbol)` ≤ 50
- 1 ≤ `len(known_venue_suffixes)` ≤ 20
- 对每个 `suffix`,1 ≤ `len(suffix)` ≤ 5;后缀仅含字母(a-z / A-Z)
- 符号可包含 ASCII 字母、数字、点号和任意 Unicode 空白;不含其它标点
- 输出是 `dict[str, list[str]]`,键为规整形式,值为按输入顺序排列的原始符号列表;以精确比较为准(无浮点容差)
样例
Case 1 · statement-example: cross-venue dedup with whitespace and case
输入: [["aapl","AAPL.US"," aapl ","AAPL"],["HK","US","LSE"]]
期望: {"AAPL":["aapl","AAPL.US"," aapl ","AAPL"]}
四个原始符号都规整为 AAPL:小写补齐为大写,首尾空白去掉,'.US' 被作为已知场所后缀剥离。
Case 2 · statement-example: multi-venue grouping preserves input order
输入: [["0700.HK","AAPL.US","VOD.LSE","0700.hk"],["HK","US","LSE"]]
期望: {"0700":["0700.HK","0700.hk"],"AAPL":["AAPL.US"],"VOD":["VOD.LSE"]}
三个不同场所的代码各自分组;场所后缀匹配是大小写不敏感的,所以 '0700.hk' 和 '0700.HK' 归并到同一规整键 '0700'。
Case 3 · statement-example: basic uppercase normalization no venue
输入: [["msft","MSFT","Msft"],["HK"]]
期望: {"MSFT":["msft","MSFT","Msft"]}
没有任何已知场所后缀,只做大小写归一,三种写法都规整为 MSFT。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: cross-venue dedup with whitespace and case
输入: [["aapl","AAPL.US"," aapl ","AAPL"],["HK","US","LSE"]]
期望: {"AAPL":["aapl","AAPL.US"," aapl ","AAPL"]}
四个原始符号都规整为 AAPL:小写补齐为大写,首尾空白去掉,'.US' 被作为已知场所后缀剥离。
Case 2 · statement-example: multi-venue grouping preserves input order
输入: [["0700.HK","AAPL.US","VOD.LSE","0700.hk"],["HK","US","LSE"]]
期望: {"0700":["0700.HK","0700.hk"],"AAPL":["AAPL.US"],"VOD":["VOD.LSE"]}
三个不同场所的代码各自分组;场所后缀匹配是大小写不敏感的,所以 '0700.hk' 和 '0700.HK' 归并到同一规整键 '0700'。
Case 3 · statement-example: basic uppercase normalization no venue
输入: [["msft","MSFT","Msft"],["HK"]]
期望: {"MSFT":["msft","MSFT","Msft"]}
没有任何已知场所后缀,只做大小写归一,三种写法都规整为 MSFT。