← 返回编程题库
coding-expected-rwa-after-rating-migration中等免费版2000ms未尝试

评级迁移 H 步后的组合期望 RWA

Expected Portfolio RWA After H Rating-Migration Steps

开始编码

实现 solution(distribution: list[float], transition_matrix: list[list[float]], rwa_per_rating: list[float], horizon: int) -> float。某信用风险条线希望预测未来某一期组合每单位名义本金对应的期望 RWA(风险加权资产):给定 (i) 当前评级状态分布 distribution、(ii) 由历史评级迁移数据估计得到的一期评级转移矩阵 transition_matrix、(iii) 各评级的 RWA 贡献向量 rwa_per_rating[k](处于评级 k 的债务人每单位名义本金消耗的 RWA 美元数)。把分布与转移矩阵相乘 H 次得到 H 期后的分布,再与 RWA 向量做点积:

distribution_h = distribution @ transition_matrix^H        # K 维向量
expected_rwa   = sum over k of distribution_h[k] * rwa_per_rating[k]

转移矩阵是行随机的——transition_matrix[i][j] 表示 FROM-i-TO-j 的概率,每一(不是每一列)之和为 1.0。每一步传播为

new_dist[j] = sum_{i in [0, K)} dist[i] * transition_matrix[i][j]

i评级、j目标评级。与 rwa_per_rating 的点积**只在 H 步传播之后做一次不要**写在循环里。

solution([0.6, 0.3, 0.1], [[0.85, 0.10, 0.05], [0.10, 0.80, 0.10], [0.0, 0.0, 1.0]], [0.2, 0.5, 1.5], 2) 返回 0.5703。该转移矩阵是行随机的——第 0 行 [0.85, 0.10, 0.05] 之和 = 1.0、第 1 行 [0.10, 0.80, 0.10] 之和 = 1.0、第 2 行 [0.0, 0.0, 1.0] 是吸收的违约态。第 1 步:new_dist[0] = 0.6*0.85 + 0.3*0.10 + 0.1*0.0 = 0.54new_dist[1] = 0.6*0.10 + 0.3*0.80 + 0.1*0.0 = 0.30new_dist[2] = 0.6*0.05 + 0.3*0.10 + 0.1*1.0 = 0.16,所以 1 步后分布是 [0.54, 0.30, 0.16]。第 2 步:new_dist[0] = 0.54*0.85 + 0.30*0.10 + 0.16*0.0 = 0.489new_dist[1] = 0.54*0.10 + 0.30*0.80 + 0.16*0.0 = 0.294new_dist[2] = 0.54*0.05 + 0.30*0.10 + 0.16*1.0 = 0.217。最终点积:0.489*0.2 + 0.294*0.5 + 0.217*1.5 = 0.0978 + 0.147 + 0.3255 = 0.5703。期望 RWA 为每单位组合名义本金 0.5703——再乘以组合总名义本金即可得到 H=2 期末的美元 RWA。

行 vs 列约定的索引校验:行随机的前向公式取 tm[i][j](FROM i TO j)、对 i 求和。如果作者误写成 new_dist[j] = sum_i dist[i] * tm[j][i](这种索引互换在列随机矩阵——列和为 1.0——下才是对的),那么本例第 1 步 new_dist[0] 会算出 0.6*0.85 + 0.3*0.10 + 0.1*0.05 = 0.575(不是正确的 0.54);H=2 后的点积会与 0.5703 显著不同。两种索引只有在对称矩阵上才碰巧吻合;非对称矩阵上必然分叉。

三个陷阱

需要明确的细节:horizon == 0 返回当前期望 RWA:sum_k distribution[k] * rwa_per_rating[k](空乘积 transition_matrix^0 = I 让分布不动)。K == 1 时矩阵必然是 [[1.0]]、输出永远等于 rwa_per_rating[0]违约吸收态 d 编码为 transition_matrix[d] = [0, 0, ..., 1.0, ..., 0, 0](对角线第 d 位是 1.0、其余为 0);循环里无需特判——吸收行就是正确的数学模型,所谓防御性的"跳过吸收态"反而会把传播弄坏。本函数不抛异常;调用方保证矩阵的行随机性、输入是合法的概率分布、RWA 贡献非负。

期望算法是简单的 O(H * K^2) 三层嵌套循环做传播,再加 O(K) 的点积:每一步先 new_dist = [0.0] * K,遍历 (i, j) 累加 new_dist[j] += dist[i] * tm[i][j],步末 dist = new_distH 步完成后再算一次 expected_rwa = sum_k dist[k] * rwa_per_rating[k]。由于 K <= 8H <= 24,总运算量约为 1500,朴素三层循环远远满足 2000 ms 上限。**每一步必须新开 new_dist**——一边读 dist[i] 一边原地写 dist[j] 会污染本轮累加。

第三个陷阱是点积位置:RWA 点积只在 H 步全部完成后、对最终分布做一次,不要写在 H 步循环内。在循环里折成 expected_rwa += sum_k dist[k] * rwa[k] 计算的是横跨 H 期的累积 RWA(H 个汇报期内期望 RWA 的路径积分),不是 H 期末的期望 RWA。两个度量只有在 H == 1 且累加器在步前归零时才会偶然吻合;在 H == 0 时累积度量返回 0.0、而正确答案返回当前期望 RWA,所以可见的 H=0 用例就能干净地暴露这个 bug。

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

实践背景

某信用风险条线根据历史评级迁移数据(例如机构内部企业信贷池逐月观察到的内评迁移)估计出一张一期转移矩阵;又根据 Basel 内评法(IRB)下风险权重函数对各评级桶的中位 PD/LGD 应用得到了各评级的 RWA 密度向量 rwa_per_rating[k]。要预测未来 H 个汇报期(年度资本规划取 12 个月、多年战略预测取 24 个月)的组合资本占用,将当前评级分布与转移矩阵连乘 H 次后再与 RWA 密度向量做点积。输出驱动多期资本投影——"如果继续持有 24 个月不再平衡,第 24 月组合会消耗多少 RWA?"——并喂入 Basel III IRB 资本规划、IFRS 9 下的存续期预期损失计提以及机构的全面资本分析与评估(CCAR)压力提交。违约吸收的约定至关重要:债务人一旦违约、评级迁移模型对其后续轨迹就此止步,所有从其他评级流入违约态的概率质量都留在违约态、按(较高的)违约 RWA 贡献继续累计——这恰好就是"对应行除对角线 1.0 之外全 0"所编码的内容。行随机索引是条线下游所有数据管道和存续期损失库默认的约定;列随机的实现会把概率质量沿时间反向传播,把资本规划面板上每一个多期 RWA 预测都弄错。

约束条件

  • 1 <= K <= 8,其中 K == len(distribution) == len(transition_matrix) == len(rwa_per_rating)
  • 0 <= horizon <= 24
  • 每个 distribution[i] 在 [0.0, 1.0];sum(distribution) == 1.0(在 rel_tol=1e-9 内)
  • 每个 transition_matrix[i] 是长度为 K 的列表;每个 transition_matrix[i][j] 在 [0.0, 1.0];每**行** i 之和为 1.0(在 rel_tol=1e-9 内)
  • 每个 rwa_per_rating[i] 在 [0.0, 1e9](非负)
  • 输出为 float;非负;按 rel_tol=1e-9、abs_tol=1e-9 比对

样例

Case 1 · statement-example: 3-state row-stochastic with rwa, H=2

输入: [[0.6,0.3,0.1],[[0.85,0.1,0.05],[0.1,0.8,0.1],[0,0,1]],[0.2,0.5,1.5],2]

期望: 0.5703

三状态行随机矩阵,H=2 步前向传播;H=2 后分布 [0.489, 0.294, 0.217],与 RWA [0.2, 0.5, 1.5] 点积。

Case 2 · visible: H=0 returns current expected RWA (no propagation)

输入: [[0.2,0.5,0.3],[[0.7,0.2,0.1],[0.1,0.8,0.1],[0,0,1]],[0.4,0.7,1.5],0]

期望: 0.8799999999999999

H=0 不做传播;输出等于初始分布与 RWA 的点积。

Case 3 · visible: K=1 trivial single-state with H=5

输入: [[1],[[1]],[0.85],5]

期望: 0.85

K=1 时矩阵恒为 [[1.0]],分布与 RWA 不变;任意 H 输出都等于 rwa[0]。

Case 4 · visible: identity transition_matrix preserves expected RWA

输入: [[0.4,0.35,0.25],[[1,0,0],[0,1,0],[0,0,1]],[0.3,0.7,1.4],7]

期望: 0.715

单位转移矩阵:每个评级以概率 1.0 留在原地;任意 H 下分布与期望 RWA 都不变。

Case 5 · visible: deterministic start [1,0,0] dotted with rwa after H=3

输入: [[1,0,0],[[0.7,0.2,0.1],[0,0.9,0.1],[0,0,1]],[0.2,0.6,1.5],3]

期望: 0.7067

起始全部位于评级 0 时,H 步后分布等于 TM^H 的第 0 行;输出为该行与 RWA 的点积。

最近提交

还没有提交记录。

编码区

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

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

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

Case 1 · statement-example: 3-state row-stochastic with rwa, H=2

输入: [[0.6,0.3,0.1],[[0.85,0.1,0.05],[0.1,0.8,0.1],[0,0,1]],[0.2,0.5,1.5],2]

期望: 0.5703

三状态行随机矩阵,H=2 步前向传播;H=2 后分布 [0.489, 0.294, 0.217],与 RWA [0.2, 0.5, 1.5] 点积。

Case 2 · visible: H=0 returns current expected RWA (no propagation)

输入: [[0.2,0.5,0.3],[[0.7,0.2,0.1],[0.1,0.8,0.1],[0,0,1]],[0.4,0.7,1.5],0]

期望: 0.8799999999999999

H=0 不做传播;输出等于初始分布与 RWA 的点积。

Case 3 · visible: K=1 trivial single-state with H=5

输入: [[1],[[1]],[0.85],5]

期望: 0.85

K=1 时矩阵恒为 [[1.0]],分布与 RWA 不变;任意 H 输出都等于 rwa[0]。

Case 4 · visible: identity transition_matrix preserves expected RWA

输入: [[0.4,0.35,0.25],[[1,0,0],[0,1,0],[0,0,1]],[0.3,0.7,1.4],7]

期望: 0.715

单位转移矩阵:每个评级以概率 1.0 留在原地;任意 H 下分布与期望 RWA 都不变。

Case 5 · visible: deterministic start [1,0,0] dotted with rwa after H=3

输入: [[1,0,0],[[0.7,0.2,0.1],[0,0.9,0.1],[0,0,1]],[0.2,0.6,1.5],3]

期望: 0.7067

起始全部位于评级 0 时,H 步后分布等于 TM^H 的第 0 行;输出为该行与 RWA 的点积。