← 返回编程题库
coding-default-correlation-from-bivariate-normal-cdf中等免费版1000ms未尝试

由一因子高斯 Copula 的二元正态 CDF 计算两户违约相关系数

Pairwise Default Correlation from One-Factor Gaussian-Copula Bivariate-CDF Inputs

开始编码

实现 solution(pd_a: float, pd_b: float, bivariate_normal_cdf_value: float) -> float。信贷风险台对每对对手方调用一次此函数,把预先算好的一因子高斯 Copula 联合违约概率转换成两户的违约相关系数,进而喂给组合级 Monte Carlo 与解析集中度调整。

输入:

  • pd_a —— 对手方 A 的单期无条件违约概率,落在 [0, 1]
  • pd_b —— 对手方 B 的单期无条件违约概率,落在 [0, 1]
  • bivariate_normal_cdf_value —— 一因子高斯 Copula 下的联合违约概率 P[A 违约 且 B 违约],等于 Phi_2(Phi^-1(pd_a), Phi^-1(pd_b); rho_asset)。调用方已经基于自己的资产相关性参数 rho_asset 算好这个二元正态 CDF;本函数只消费这个标量。

输出由如下可观测公式定义:

  1. 分子 —— 违约指示变量的协方差:numerator = bivariate_normal_cdf_value - pd_a * pd_b
  2. 分母 —— 两个单名伯努利标准差的乘积:denominator = sqrt(pd_a * (1 - pd_a) * pd_b * (1 - pd_b))
  3. 违约相关系数default_corr = numerator / denominator。带符号。

退化单名分布的哨兵:

  • pd_a == 0pd_a == 1pd_b == 0pd_b == 1,对应的违约指示变量为常数,方差为零,分母为零,违约相关系数数学上未定义。返回 float('nan')

只要 pd_apd_b 都严格在 (0, 1) 区间内,分母严格为正,除法良定义。

solution(0.02, 0.03, 0.0006) 返回 0.0pd_a = 0.02pd_b = 0.03bivariate_normal_cdf_value = 0.0006 = pd_a * pd_b,联合违约概率等于独立乘积,分子恰好为零,违约相关系数为零。这就是独立性基准——若调用方把 rho_asset = 0 传给自家 Phi_2,返回值就是 pd_a * pd_bsolution(...) 据此报出零违约相关。

同行业典型的正违约相关算例:solution(0.02, 0.03, 0.0012) 返回 (0.0012 - 0.0006) / sqrt(0.02 * 0.98 * 0.03 * 0.97) = 0.0006 / sqrt(0.000570360) = 0.0006 / 0.0238822...0.025123...。即使联合概率相对独立的基准翻了一倍(从 6e-41.2e-3),违约相关系数也只有约 0.025——百分之二点五。这正是经典的高斯 Copula 效应:当 PD 很小时,一个温和的资产相关性只会驱动出小得多的违约相关性。结果为正,因为联合违约比独立基准更频繁。

**pd_a = 0 哨兵**算例:solution(0.0, 0.05, 0.0) 返回 float('nan')。对手方 A 违约概率为零,A 的违约指示变量恒为零,方差为零,分母为零,违约相关系数未定义。注意此时 bivariate_normal_cdf_value 必为零(因为 P[A 且 B] <= P[A] = 0),但即便输入互洽,函数也必须返回 NaN——哨兵是基于退化的单名分布,不是基于分子。

边界pd_a 恰为 01 返回 NaN。pd_b 恰为 01 返回 NaN。当两个 PD 严格在 (0, 1) 时:bivariate_normal_cdf_value = pd_a * pd_b 返回 0(独立)。bivariate_normal_cdf_value > pd_a * pd_b 返回正数(正违约相关——典型情形)。bivariate_normal_cdf_value < pd_a * pd_b 返回负数(负违约相关——罕见的反周期情形)。本函数对约束区间内任何输入都不抛异常;NaN 哨兵是退化 pd in {0, 1} 四种情形的合同输出。

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

实践背景

在一因子高斯 Copula 信贷模型——监管 IRB 资本和大多数解析与 Monte Carlo 组合信贷风险引擎背后的核心架构——里,资产相关性 rho_asset 通过二元正态 CDF Phi_2(Phi^-1(pd_a), Phi^-1(pd_b); rho_asset) 参数化联合违约概率。然而风险官并不在资产相关性空间里推理。他们在违约相关性空间里推理——也就是违约二元指示变量的相关系数,这才是真正控制组合违约损失方差的量。两者是非常不同的数:典型 0.20 的资产相关性(许多公司敞口的监管锚),在 PD 处于个位数百分比时,往往只对应 0.020.10 的违约相关性,因为伯努利方差 p*(1-p) 很小,二元正态 CDF 远比单看资产相关性所暗示的离独立乘积 pd_a * pd_b 更近。solution(pd_a, pd_b, bivariate_normal_cdf_value) 是这一转换的原语:它把调用方对 Phi_2 的求值结果作为标量吃进来(Phi_2 真正的数值积分留给调用方自己信赖的二元正态例程),返回违约相关系数;该值再喂给解析栈的下一阶段——组合损失方差、大组合渐近分布、一因子集中度调整,或者全程 Monte Carlo 用的两两相关矩阵。本函数刻意把以下几条概念约定显式化——分子是联合概率减去独立乘积(指示变量的协方差,不是联合概率本身)、分母是单名标准差而非方差的乘积、答案带符号且对反周期资产对可以为负、pd in {0, 1} 是数学 NaN 而不是 0——这些正是生产信贷风控代码反复抓到的方向性错误。纯 O(1) 实现(三次乘法、一次开方、一次减法、一次除法)就是标准原语;面对几百万对手方对的生产系统按同一递推式做向量广播,但每对的合同完全相同。

约束条件

  • 0.0 <= pd_a <= 1.0
  • 0.0 <= pd_b <= 1.0
  • 0.0 <= bivariate_normal_cdf_value <= 1.0
  • 输出:float ——带符号的违约相关系数,或当 pd_a in {0,1} 或 pd_b in {0,1} 时为 NaN
  • 浮点比较器使用 rel_tol=1e-9, abs_tol=1e-9, nan_equals_nan=true

样例

Case 1 · statement-example: independence yields zero default correlation

输入: [0.02,0.03,0.0006]

期望: 0

pd_a*pd_b = 0.0006 = bivariate_cdf,分子 = 0,违约相关系数 = 0。独立性基准。

Case 2 · statement-example: positive default correlation typical of same-sector pair

输入: [0.02,0.03,0.0012]

期望: 0.025123302075452107

分子 = 0.0012 - 0.0006 = 0.0006;分母 = sqrt(0.02*0.98*0.03*0.97) = sqrt(0.000570360) ≈ 0.0238822;违约相关系数 ≈ 0.025123。

Case 3 · statement-example: pd_a equals zero returns NaN sentinel

输入: [0,0.05,0]

期望: "NaN"

pd_a = 0 -> A 的违约指示变量恒为零,方差为零,分母为零,违约相关系数未定义 -> NaN。

Case 4 · typical: equal-pd Frechet upper bound default_corr equals one

输入: [0.5,0.5,0.5]

期望: 1

pd_a = pd_b = 0.5 且 bivariate_cdf = 0.5 = min(pd_a, pd_b);A 与 B 完全同向,违约相关系数 = 1。

Case 5 · typical: equal-pd Frechet lower bound default_corr equals minus one

输入: [0.5,0.5,0]

期望: -1

pd_a = pd_b = 0.5 且 bivariate_cdf = 0;A 与 B 从不同时违约(Frechet 下界),违约相关系数 = -1。

Case 6 · typical: equal-pd independence yields zero default correlation

输入: [0.5,0.5,0.25]

期望: 0

pd_a*pd_b = 0.25 = bivariate_cdf;分子 = 0;违约相关系数 = 0。

Case 7 · typical: asymmetric pds joint twice the independent product

输入: [0.1,0.2,0.04]

期望: 0.1666666666666666

分子 = 0.04 - 0.02 = 0.02;分母 = sqrt(0.1*0.9*0.2*0.8) = sqrt(0.0144) = 0.12;违约相关系数 = 0.02/0.12 = 1/6。

Case 8 · typical: asymmetric pds at Frechet upper bound

输入: [0.1,0.2,0.1]

期望: 0.6666666666666665

min(pd_a, pd_b) = 0.1 = bivariate_cdf(Frechet 上界)。分子 = 0.1 - 0.02 = 0.08;分母 = sqrt(0.0144) = 0.12;违约相关系数 = 0.08/0.12 = 2/3。

Case 9 · typical: asymmetric pds independence

输入: [0.1,0.2,0.02]

期望: -2.891205793294678e-17

pd_a*pd_b = 0.02 = bivariate_cdf;违约相关系数 = 0(浮点残差在容差以内)。

Case 10 · typical: low pds with multiple-of-independence joint default

输入: [0.01,0.02,0.001]

期望: 0.05743073230052641

分子 = 0.001 - 0.0002 = 0.0008;分母 = sqrt(0.01*0.99*0.02*0.98) = sqrt(0.00019404) ≈ 0.01393;违约相关系数 ≈ 0.0574。

Case 11 · typical: negative default correlation counter-cyclical sector pair

输入: [0.3,0.4,0.05]

期望: -0.31180478223116176

分子 = 0.05 - 0.12 = -0.07;分母 = sqrt(0.3*0.7*0.4*0.6) = sqrt(0.0504) ≈ 0.22450;违约相关系数 ≈ -0.3118。

Case 12 · typical: high pds with negative default correlation

输入: [0.7,0.8,0.5]

期望: -0.32732683535398827

分子 = 0.5 - 0.56 = -0.06;分母 = sqrt(0.7*0.3*0.8*0.2) = sqrt(0.0336) ≈ 0.1833;违约相关系数 ≈ -0.3273。

Case 13 · typical: high pds with positive default correlation

输入: [0.7,0.8,0.65]

期望: 0.4909902530309833

分子 = 0.65 - 0.56 = 0.09;分母 = sqrt(0.0336) ≈ 0.1833;违约相关系数 ≈ 0.4910。

Case 14 · typical: high pds independence

输入: [0.7,0.8,0.56]

期望: 6.056763153128097e-16

pd_a*pd_b = 0.56 = bivariate_cdf;违约相关系数 = 0(浮点残差在容差以内)。

Case 15 · typical: very small pds joint five-times the independent product

输入: [0.001,0.002,0.00001]

期望: 0.00566535298820771

分子 = 1e-5 - 2e-6 = 8e-6;分母 = sqrt(0.001*0.999*0.002*0.998) ≈ 0.001412;违约相关系数 ≈ 0.005665。

Case 16 · boundary: pd_a equals one returns NaN sentinel

输入: [1,0.05,0.05]

期望: "NaN"

pd_a = 1 -> A 的违约指示变量恒为 1,方差为零,分母为零 -> NaN。

Case 17 · boundary: pd_b equals zero returns NaN sentinel

输入: [0.05,0,0]

期望: "NaN"

pd_b = 0 -> B 的违约指示变量恒为零,方差为零,分母为零 -> NaN。

Case 18 · boundary: pd_b equals one returns NaN sentinel

输入: [0.05,1,0.05]

期望: "NaN"

pd_b = 1 -> B 的违约指示变量恒为 1,方差为零 -> NaN。

Case 19 · boundary: both pds zero returns NaN sentinel

输入: [0,0,0]

期望: "NaN"

两个 pd 都为 0;两个指示变量都退化;NaN。

Case 20 · boundary: both pds one returns NaN sentinel

输入: [1,1,1]

期望: "NaN"

两个 pd 都为 1;两个指示变量都恒为 1;NaN。

最近提交

还没有提交记录。

编码区

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

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

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

Case 1 · statement-example: independence yields zero default correlation

输入: [0.02,0.03,0.0006]

期望: 0

pd_a*pd_b = 0.0006 = bivariate_cdf,分子 = 0,违约相关系数 = 0。独立性基准。

Case 2 · statement-example: positive default correlation typical of same-sector pair

输入: [0.02,0.03,0.0012]

期望: 0.025123302075452107

分子 = 0.0012 - 0.0006 = 0.0006;分母 = sqrt(0.02*0.98*0.03*0.97) = sqrt(0.000570360) ≈ 0.0238822;违约相关系数 ≈ 0.025123。

Case 3 · statement-example: pd_a equals zero returns NaN sentinel

输入: [0,0.05,0]

期望: "NaN"

pd_a = 0 -> A 的违约指示变量恒为零,方差为零,分母为零,违约相关系数未定义 -> NaN。

Case 4 · typical: equal-pd Frechet upper bound default_corr equals one

输入: [0.5,0.5,0.5]

期望: 1

pd_a = pd_b = 0.5 且 bivariate_cdf = 0.5 = min(pd_a, pd_b);A 与 B 完全同向,违约相关系数 = 1。

Case 5 · typical: equal-pd Frechet lower bound default_corr equals minus one

输入: [0.5,0.5,0]

期望: -1

pd_a = pd_b = 0.5 且 bivariate_cdf = 0;A 与 B 从不同时违约(Frechet 下界),违约相关系数 = -1。

Case 6 · typical: equal-pd independence yields zero default correlation

输入: [0.5,0.5,0.25]

期望: 0

pd_a*pd_b = 0.25 = bivariate_cdf;分子 = 0;违约相关系数 = 0。

Case 7 · typical: asymmetric pds joint twice the independent product

输入: [0.1,0.2,0.04]

期望: 0.1666666666666666

分子 = 0.04 - 0.02 = 0.02;分母 = sqrt(0.1*0.9*0.2*0.8) = sqrt(0.0144) = 0.12;违约相关系数 = 0.02/0.12 = 1/6。

Case 8 · typical: asymmetric pds at Frechet upper bound

输入: [0.1,0.2,0.1]

期望: 0.6666666666666665

min(pd_a, pd_b) = 0.1 = bivariate_cdf(Frechet 上界)。分子 = 0.1 - 0.02 = 0.08;分母 = sqrt(0.0144) = 0.12;违约相关系数 = 0.08/0.12 = 2/3。

Case 9 · typical: asymmetric pds independence

输入: [0.1,0.2,0.02]

期望: -2.891205793294678e-17

pd_a*pd_b = 0.02 = bivariate_cdf;违约相关系数 = 0(浮点残差在容差以内)。

Case 10 · typical: low pds with multiple-of-independence joint default

输入: [0.01,0.02,0.001]

期望: 0.05743073230052641

分子 = 0.001 - 0.0002 = 0.0008;分母 = sqrt(0.01*0.99*0.02*0.98) = sqrt(0.00019404) ≈ 0.01393;违约相关系数 ≈ 0.0574。

Case 11 · typical: negative default correlation counter-cyclical sector pair

输入: [0.3,0.4,0.05]

期望: -0.31180478223116176

分子 = 0.05 - 0.12 = -0.07;分母 = sqrt(0.3*0.7*0.4*0.6) = sqrt(0.0504) ≈ 0.22450;违约相关系数 ≈ -0.3118。

Case 12 · typical: high pds with negative default correlation

输入: [0.7,0.8,0.5]

期望: -0.32732683535398827

分子 = 0.5 - 0.56 = -0.06;分母 = sqrt(0.7*0.3*0.8*0.2) = sqrt(0.0336) ≈ 0.1833;违约相关系数 ≈ -0.3273。

Case 13 · typical: high pds with positive default correlation

输入: [0.7,0.8,0.65]

期望: 0.4909902530309833

分子 = 0.65 - 0.56 = 0.09;分母 = sqrt(0.0336) ≈ 0.1833;违约相关系数 ≈ 0.4910。

Case 14 · typical: high pds independence

输入: [0.7,0.8,0.56]

期望: 6.056763153128097e-16

pd_a*pd_b = 0.56 = bivariate_cdf;违约相关系数 = 0(浮点残差在容差以内)。

Case 15 · typical: very small pds joint five-times the independent product

输入: [0.001,0.002,0.00001]

期望: 0.00566535298820771

分子 = 1e-5 - 2e-6 = 8e-6;分母 = sqrt(0.001*0.999*0.002*0.998) ≈ 0.001412;违约相关系数 ≈ 0.005665。

Case 16 · boundary: pd_a equals one returns NaN sentinel

输入: [1,0.05,0.05]

期望: "NaN"

pd_a = 1 -> A 的违约指示变量恒为 1,方差为零,分母为零 -> NaN。

Case 17 · boundary: pd_b equals zero returns NaN sentinel

输入: [0.05,0,0]

期望: "NaN"

pd_b = 0 -> B 的违约指示变量恒为零,方差为零,分母为零 -> NaN。

Case 18 · boundary: pd_b equals one returns NaN sentinel

输入: [0.05,1,0.05]

期望: "NaN"

pd_b = 1 -> B 的违约指示变量恒为 1,方差为零 -> NaN。

Case 19 · boundary: both pds zero returns NaN sentinel

输入: [0,0,0]

期望: "NaN"

两个 pd 都为 0;两个指示变量都退化;NaN。

Case 20 · boundary: both pds one returns NaN sentinel

输入: [1,1,1]

期望: "NaN"

两个 pd 都为 1;两个指示变量都恒为 1;NaN。