← 返回编程题库
coding-lgd-beta-distribution-method-of-moments中等免费版2000ms未尝试

基于矩匹配的违约损失率(LGD)Beta 分布校准

LGD Beta-Distribution Calibration via Method of Moments

开始编码

实现 solution(mean_lgd: float, std_lgd: float) -> list[float]。某信用风险口要把 LGD 分布校准到一组目标均值和标准差,做法是用矩匹配把 Beta 分布拟合到这两个矩。两个标量输入:目标均值 mean_lgd(严格位于 (0, 1))和目标标准差 std_lgd(非负)。返回 [alpha_param, beta_param]——匹配的 Beta 参数。

矩匹配共四步。第 1 步:把标准差平方得方差 v = std_lgd * std_lgd。第 2 步:计算 Bernoulli 上界 bound = mean_lgd * (1 - mean_lgd) 并校验 v < bound;任何 [0, 1] 上支撑的随机变量(含 Beta)方差都严格小于 bound,因此 v >= bound 时无 Beta 匹配。第 3 步:算缩放因子 s = bound / v - 1(等于 alpha + beta)。第 4 步:按均值切分 alpha_param = mean_lgd * sbeta_param = (1 - mean_lgd) * s。所得 Beta 的均值与方差正好是 (m, v)

solution(0.5, 0.2) 返回 [2.625, 2.625]。逐步:方差 v = 0.04。上界 = 0.5 * 0.5 = 0.25v=0.04 < 0.25,校验通过。缩放 s = 0.25 / 0.04 - 1 = 5.25。切分 alpha = 0.5 * 5.25 = 2.625beta = 0.5 * 5.25 = 2.625。对称 Beta 与 m=0.5(无偏)+ 中等波动一致。

第二个例子。solution(0.4, 0.1) 返回 [9.2, 13.8]v = 0.01bound = 0.4 * 0.6 = 0.24s = 0.24/0.01 - 1 = 23alpha = 0.4*23 = 9.2beta = 0.6*23 = 13.8mean<0.5 时 Beta 右偏。

哨兵与陷阱

两个哨兵让规约在声明区间内闭合。其一,std_lgd == 0 时方差为 0,公式给出 s = m*(1-m)/0 = +infalpha = m*sbeta = (1-m)*s 均为 +inf。规约返回 [float('inf'), float('inf')]。无穷参数的 Beta 极限就是 mean 处的 Dirac 点质量——"无离散度"的自然退化校准。要在平方之前识别 std_lgd == 0,避免依赖 1/0 的 IEEE 行为。其二,v >= mean*(1-mean) 时矩匹配无 Beta 解:[0, 1] 上的 Beta 方差受 mean*(1-mean) 上界(Bernoulli 上界)约束。规约返回 [float('nan'), float('nan')]。要在算 s 之前识别这种情形,否则 s 变非正、公式会输出的 Beta 参数——这不是合法解。

五个陷阱:

  1. 方差,不是标准差。先平方:v = std_lgd * std_lgd。直接把 std_lgd 塞进 m*(1-m)/std - 1 会产生量纲错误的 s,与矩匹配答案大相径庭。
  2. 有效性上界,不是仅非零。判定是 v < mean*(1-mean),不是 v > 0。漏掉判定会让 s 在高方差输入下变负、并输出负的 alpha/beta——永远不是合法 Beta 参数。Python 容忍这种数学不代表它正确。
  3. **alpha = m*s、不是 (1-m)*s**。Beta(a, b) 的均值是 a/(a+b),所以"均值侧"参数是 alpha。把方向写反会让 alpha 与 beta 互换;得到的 Beta 均值变成 1-m 而不是 m——一种数字仍然像样的隐性 bug(本测试套中的镜像用例会抓到)。
  4. 二元 list、顺序固定为 [alpha, beta]。返回 tuple、NumPy 数组、标量、或 [beta, alpha] 都违约。比对器按 ordered: true 逐元素比。
  5. **std_lgd == 0 返回 [+inf, +inf]不是 [NaN, NaN]**。两个哨兵含义不同:+inf 表"校准为均值处点质量";NaN 表"该矩组合无 Beta 可匹配"。混用会让按哨兵种类分支的下游模拟器走错路径。

函数 O(1) 时间、O(1) 空间——无循环、除两元素输出外无分配。

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

实践背景

在 IFRS 9 / Basel IRB 下,银行将 LGD 分布建模为 [0, 1] 上的 Beta,原因是:(a) 支撑区间天然契合 LGD 的取值范围;(b) 两个参数恰好够固定历史抵押与回收数据所给出的两个关键输入——均值与波动率。矩匹配从 (m, s) 直接给出闭式 Beta 参数,无需迭代优化。在工程上这是给入随机信用损失模拟前的校准步骤:(alpha, beta) 一旦定下来,模拟器就从 Beta(alpha, beta) 抽样生成逐户 LGD 情景;与 PD 情景、EAD 组合后形成蒙特卡洛损失分布,喂入经济资本与 IFRS 9 stage-2/stage-3 拨备。五个陷阱中的任何一个写错——方差/标准差、有效性上界、参数方向、输出形状、退化哨兵种类——都会直接传导到 Monte-Carlo 损失分布以及上报的监管与会计数字。

约束条件

  • 0.001 <= mean_lgd <= 0.999(LGD 目标均值,严格在开单位区间内)
  • 0.0 <= std_lgd <= 0.5(LGD 目标标准差,非负)
  • 输出为 list[float],长度 2:[alpha_param, beta_param],可行时均为正;std_lgd==0 时均为 +inf;v >= mean*(1-mean) 时均为 NaN
  • 全部按 rel_tol=1e-9、abs_tol=1e-9 比对;nan_equals_nan 为 true
  • 在声明区间内的任何输入都不得抛异常

样例

Case 1 · statement-example: mean=0.5, std=0.2 symmetric Beta

输入: [0.5,0.2]

期望: [2.6249999999999996,2.6249999999999996]

v=0.04;m*(1-m)=0.25;s=0.25/0.04-1=5.25;alpha=0.5*5.25=2.625;beta=0.5*5.25=2.625;对称 Beta。

Case 2 · statement-example: mean=0.4, std=0.1 asymmetric Beta

输入: [0.4,0.1]

期望: [9.199999999999998,13.799999999999995]

v=0.01;m*(1-m)=0.24;s=0.24/0.01-1=23;alpha=0.4*23=9.2;beta=0.6*23=13.8;右偏的 LGD 形态。

Case 3 · typical: mean=0.3, std=0.1 mid-low LGD

输入: [0.3,0.1]

期望: [5.999999999999999,13.999999999999996]

v=0.01;m*(1-m)=0.21;s=20;alpha=6;beta=14;mean<0.5 时 alpha<beta。

Case 4 · typical: mean=0.7, std=0.15 high LGD bucket

输入: [0.7,0.15]

期望: [5.833333333333333,2.5000000000000004]

v=0.0225;m*(1-m)=0.21;s=0.21/0.0225-1=8.333...;alpha=0.7*s≈5.833;beta=0.3*s=2.5。

Case 5 · typical: mean=0.25, std=0.2 wide-volatility low-mean Beta

输入: [0.25,0.2]

期望: [0.9218749999999998,2.765624999999999]

v=0.04;m*(1-m)=0.1875;s=0.1875/0.04-1=3.6875;alpha=0.25*s≈0.9219;beta=0.75*s≈2.7656;s 较小 -> Beta 接近 U 形端点厚尾。

Case 6 · typical: mean=0.75, std=0.2 mirror of 0.25 case (alpha<->beta swap)

输入: [0.75,0.2]

期望: [2.765624999999999,0.9218749999999998]

镜像于 mean=0.25 的情形:alpha 与 beta 互换。验证作者没有把 alpha 写成 (1-m)*s。

Case 7 · typical: mean=0.6, std=0.25 broad LGD distribution

输入: [0.6,0.25]

期望: [1.704,1.136]

v=0.0625;m*(1-m)=0.24;s=0.24/0.0625-1=2.84;alpha=0.6*2.84=1.704;beta=0.4*2.84=1.136。

Case 8 · typical: mean=0.45, std=0.15 near-symmetric calibration

输入: [0.45,0.15]

期望: [4.500000000000001,5.500000000000002]

v=0.0225;m*(1-m)=0.2475;s=10;alpha=0.45*10=4.5;beta=0.55*10=5.5。

Case 9 · typical: mean=0.55, std=0.15 mirror near-symmetric calibration

输入: [0.55,0.15]

期望: [5.5,4.5]

镜像于 mean=0.45:alpha=5.5、beta=4.5;再次验证 alpha=m*s 的方向。

Case 10 · typical: mean=0.2, std=0.1 left-skew calibration

输入: [0.2,0.1]

期望: [3,12]

v=0.01;m*(1-m)=0.16;s=15;alpha=0.2*15=3;beta=0.8*15=12;alpha+beta=15。

Case 11 · typical: mean=0.8, std=0.1 right-skew mirror of 0.2

输入: [0.8,0.1]

期望: [11.999999999999996,2.9999999999999982]

镜像于 mean=0.2,alpha 与 beta 互换;alpha=12、beta=3。

Case 12 · typical: mean=0.5, std=0.1 tight symmetric distribution

输入: [0.5,0.1]

期望: [11.999999999999998,11.999999999999998]

v=0.01;m*(1-m)=0.25;s=24;alpha=beta=12。

Case 13 · boundary: std=0 degenerate point mass returns [+inf, +inf]

输入: [0.5,0]

期望: ["Infinity","Infinity"]

std=0 触发哨兵:方差 0 时 s = m*(1-m)/0 -> +inf;alpha=beta=+inf;表示 Beta 退化为 mean 处的 Dirac 点质量。

Case 14 · boundary: variance == m*(1-m) exactly returns [NaN, NaN]

输入: [0.5,0.5]

期望: ["NaN","NaN"]

v=0.25 等于 m*(1-m)=0.25 的边界:Beta 分布的方差严格小于 m*(1-m),无 Beta 匹配;返回 [NaN, NaN]。

Case 15 · boundary: variance > m*(1-m) returns [NaN, NaN]

输入: [0.6,0.5]

期望: ["NaN","NaN"]

v=0.25 > m*(1-m)=0.24:超过 Bernoulli 方差上界,无 Beta 匹配;返回 [NaN, NaN]。

Case 16 · boundary: variance just below m*(1-m) yields very small s

输入: [0.5,0.49]

期望: [0.020616409829237847,0.020616409829237847]

v=0.2401 接近上界 0.25:s=0.25/0.2401-1≈0.0412;alpha=beta≈0.0206;Beta 形状极度向 0/1 端点集中。

Case 17 · boundary: small variance large s mean=0.5 std=0.05

输入: [0.5,0.05]

期望: [49.49999999999999,49.49999999999999]

v=0.0025;m*(1-m)=0.25;s=99;alpha=beta=49.5;s 大 -> Beta 集中在 mean 附近。

最近提交

还没有提交记录。

编码区

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

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

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

Case 1 · statement-example: mean=0.5, std=0.2 symmetric Beta

输入: [0.5,0.2]

期望: [2.6249999999999996,2.6249999999999996]

v=0.04;m*(1-m)=0.25;s=0.25/0.04-1=5.25;alpha=0.5*5.25=2.625;beta=0.5*5.25=2.625;对称 Beta。

Case 2 · statement-example: mean=0.4, std=0.1 asymmetric Beta

输入: [0.4,0.1]

期望: [9.199999999999998,13.799999999999995]

v=0.01;m*(1-m)=0.24;s=0.24/0.01-1=23;alpha=0.4*23=9.2;beta=0.6*23=13.8;右偏的 LGD 形态。

Case 3 · typical: mean=0.3, std=0.1 mid-low LGD

输入: [0.3,0.1]

期望: [5.999999999999999,13.999999999999996]

v=0.01;m*(1-m)=0.21;s=20;alpha=6;beta=14;mean<0.5 时 alpha<beta。

Case 4 · typical: mean=0.7, std=0.15 high LGD bucket

输入: [0.7,0.15]

期望: [5.833333333333333,2.5000000000000004]

v=0.0225;m*(1-m)=0.21;s=0.21/0.0225-1=8.333...;alpha=0.7*s≈5.833;beta=0.3*s=2.5。

Case 5 · typical: mean=0.25, std=0.2 wide-volatility low-mean Beta

输入: [0.25,0.2]

期望: [0.9218749999999998,2.765624999999999]

v=0.04;m*(1-m)=0.1875;s=0.1875/0.04-1=3.6875;alpha=0.25*s≈0.9219;beta=0.75*s≈2.7656;s 较小 -> Beta 接近 U 形端点厚尾。

Case 6 · typical: mean=0.75, std=0.2 mirror of 0.25 case (alpha<->beta swap)

输入: [0.75,0.2]

期望: [2.765624999999999,0.9218749999999998]

镜像于 mean=0.25 的情形:alpha 与 beta 互换。验证作者没有把 alpha 写成 (1-m)*s。

Case 7 · typical: mean=0.6, std=0.25 broad LGD distribution

输入: [0.6,0.25]

期望: [1.704,1.136]

v=0.0625;m*(1-m)=0.24;s=0.24/0.0625-1=2.84;alpha=0.6*2.84=1.704;beta=0.4*2.84=1.136。

Case 8 · typical: mean=0.45, std=0.15 near-symmetric calibration

输入: [0.45,0.15]

期望: [4.500000000000001,5.500000000000002]

v=0.0225;m*(1-m)=0.2475;s=10;alpha=0.45*10=4.5;beta=0.55*10=5.5。

Case 9 · typical: mean=0.55, std=0.15 mirror near-symmetric calibration

输入: [0.55,0.15]

期望: [5.5,4.5]

镜像于 mean=0.45:alpha=5.5、beta=4.5;再次验证 alpha=m*s 的方向。

Case 10 · typical: mean=0.2, std=0.1 left-skew calibration

输入: [0.2,0.1]

期望: [3,12]

v=0.01;m*(1-m)=0.16;s=15;alpha=0.2*15=3;beta=0.8*15=12;alpha+beta=15。

Case 11 · typical: mean=0.8, std=0.1 right-skew mirror of 0.2

输入: [0.8,0.1]

期望: [11.999999999999996,2.9999999999999982]

镜像于 mean=0.2,alpha 与 beta 互换;alpha=12、beta=3。

Case 12 · typical: mean=0.5, std=0.1 tight symmetric distribution

输入: [0.5,0.1]

期望: [11.999999999999998,11.999999999999998]

v=0.01;m*(1-m)=0.25;s=24;alpha=beta=12。

Case 13 · boundary: std=0 degenerate point mass returns [+inf, +inf]

输入: [0.5,0]

期望: ["Infinity","Infinity"]

std=0 触发哨兵:方差 0 时 s = m*(1-m)/0 -> +inf;alpha=beta=+inf;表示 Beta 退化为 mean 处的 Dirac 点质量。

Case 14 · boundary: variance == m*(1-m) exactly returns [NaN, NaN]

输入: [0.5,0.5]

期望: ["NaN","NaN"]

v=0.25 等于 m*(1-m)=0.25 的边界:Beta 分布的方差严格小于 m*(1-m),无 Beta 匹配;返回 [NaN, NaN]。

Case 15 · boundary: variance > m*(1-m) returns [NaN, NaN]

输入: [0.6,0.5]

期望: ["NaN","NaN"]

v=0.25 > m*(1-m)=0.24:超过 Bernoulli 方差上界,无 Beta 匹配;返回 [NaN, NaN]。

Case 16 · boundary: variance just below m*(1-m) yields very small s

输入: [0.5,0.49]

期望: [0.020616409829237847,0.020616409829237847]

v=0.2401 接近上界 0.25:s=0.25/0.2401-1≈0.0412;alpha=beta≈0.0206;Beta 形状极度向 0/1 端点集中。

Case 17 · boundary: small variance large s mean=0.5 std=0.05

输入: [0.5,0.05]

期望: [49.49999999999999,49.49999999999999]

v=0.0025;m*(1-m)=0.25;s=99;alpha=beta=49.5;s 大 -> Beta 集中在 mean 附近。