← 返回编程题库
coding-counterparty-notional-aggregator简单免费版2000ms未尝试

对手方毛敞口聚合器:按规模排序的汇总表

Counterparty Gross-Notional Aggregator: Magnitude-Sorted Roll-Up

开始编码

实现 solution(cp_ids: list[int], signed_notionals: list[float]) -> list[list]。某交易台的合规面板接收两条长度均为 N 的平行数组:cp_ids[i] 是第 i 笔交易的整数对手方 ID,signed_notionals[i] 是该笔交易的带符号 float notional——正值为买边 notional、负值为卖边 notional。同一对手方的交易在输入中出现的位置任意。

对于 cp_ids每个不同的对手方 ID,计算毛敞口总额:所有满足 cp_ids[i] == cp 的下标 i 上的 abs(signed_notionals[i]) 之和。返回长度等于不同对手方 ID 个数的 [cp_id, total_abs_notional] 行表,按 total_abs_notional 降序排列,相等时按 cp_id 升序破除并列。

solution([7, 3, 7, 5, 3], [100.0, -200.0, 50.0, 400.0, 150.0]) 返回 [[5, 400.0], [3, 350.0], [7, 150.0]]。逐项扫描:CP 7 经过 +100+50 两笔,毛敞口总额 100 + 50 = 150。CP 3 经过 -200+150,总额 200 + 150 = 350——我们对绝对值求和,所以卖边 -200 与买边 +150 都计入毛敞口、不会抵消为 -50。CP 5 仅一笔 +400,总额为 400。按总额降序得 5 (400) > 3 (350) > 7 (150),本例无并列、无需触发次键。

并列时的次键示例:solution([2, 1], [50.0, 50.0]) 返回 [[1, 50.0], [2, 50.0]]。两 CP 的毛总均为 50.0,按 cp_id 升序破并列、CP 1 先于 CP 2 输出。

需要明确的细节:N == 0 返回 []。同一 cp_id 的所有交易塌缩为单行。total 字段恒为 float(从 0.0 累加),即便所有输入 notional 都是整数值。本函数不抛异常——调用方保证 len(cp_ids) == len(signed_notionals) 与约束区间内的取值,输出始终是良构表。

期望算法:单遍 O(N) 配 dict[cp_id] -> 当前毛总,再对 (N_distinct) 项做一次 sorted、键为 (-total, cp_id),两向排序一并完成。循环对象是交易而不是 CP,所以没有需要担心的边界 off-by-one。

实现细节由 stubs/stub.py 提供。

实践背景

每个交易日盘后,合规面板会把交易台对每个对手方的毛敞口汇总一次——对今日做过单的每个 CP,今日总共流过这条关系的 notional 是多少,买卖两边对称看待。汇总取而非净,是因为合规关心的问题是"今日有多少经济流量穿过该 CP"而不是"与该 CP 的剩余持仓是多少"——同一 CP 上买入 5 亿、卖出 5 亿仍然搬动了 10 亿的流量,即便净额为 0,毛额才是逐 CP 敞口上限要看的指标。输出按规模降序让交易台最大的对手方排在报表第一行——合规官员的目光最先落处——而 ID 升序的确定性破并列规则保证两个总额相同的 CP 在每次重跑中顺序一致,昨日报表与今日报表的 diff 不会被一次"仅排序顺序漂动"的偶发交换污染。基于 dict 的单遍聚合是盘后流水的标准模式:键为对手方 ID、值为累计总额、输出为按复合键稳定排序的表。

约束条件

  • 0 <= N <= 5000,其中 N 为 len(cp_ids) == len(signed_notionals)
  • 0 <= cp_ids[i] <= 1e9(非负整数对手方 ID)
  • abs(signed_notionals[i]) <= 1e9(带符号 float;正值为买边 notional、负值为卖边 notional)
  • 调用方保证 len(cp_ids) == len(signed_notionals)
  • 输出为长度等于 cp_ids 中不同 cp_id 数的 list[list[int, float]],float 字段按 rel_tol=1e-9 比对

样例

Case 1 · statement-example: 5-trade aggregator with sell rolling into gross

输入: [[7,3,7,5,3],[100,-200,50,400,150]]

期望: [[5,400],[3,350],[7,150]]

CP 7: |100|+|50|=150;CP 3: |-200|+|150|=350;CP 5: |400|=400。按总额降序:5 (400) > 3 (350) > 7 (150)。

Case 2 · visible: tied totals broken by ascending cp_id

输入: [[2,1],[50,50]]

期望: [[1,50],[2,50]]

两 CP 总额都是 50.0,按 cp_id 升序破并列,CP 1 在前。

Case 3 · visible: empty input returns empty list

输入: [[],[]]

期望: []

N=0 没有交易,返回空列表。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · statement-example: 5-trade aggregator with sell rolling into gross

输入: [[7,3,7,5,3],[100,-200,50,400,150]]

期望: [[5,400],[3,350],[7,150]]

CP 7: |100|+|50|=150;CP 3: |-200|+|150|=350;CP 5: |400|=400。按总额降序:5 (400) > 3 (350) > 7 (150)。

Case 2 · visible: tied totals broken by ascending cp_id

输入: [[2,1],[50,50]]

期望: [[1,50],[2,50]]

两 CP 总额都是 50.0,按 cp_id 升序破并列,CP 1 在前。

Case 3 · visible: empty input returns empty list

输入: [[],[]]

期望: []

N=0 没有交易,返回空列表。