← 返回编程题库
coding-min-stress-factor-keep-cp-within-cap困难免费版2000ms未尝试

最小压力情景严重度因子:首次有对手方击穿配额

Smallest Stress Severity Factor Where a Counterparty First Breaches Its Cap

开始编码

实现 solution(base_exposure: list[float], cap: list[float], stress_multiplier: list[float], tol: float) -> float。一个信用风险台持有 N 个对手方头寸。对手方 i 的无压敞口为 base_exposure[i] > 0,硬配额为 cap[i] > 0,压力情景放大因子为 stress_multiplier[i] >= 1.0。在严重度因子 f[0, 1] 下,对手方 i 的压力后敞口为

exposure_i(f) = base_exposure[i] * (1 + f * (stress_multiplier[i] - 1))

f = 0 表示不施压(敞口保持为 base_exposure[i]),f = 1 表示满压(敞口缩放至 base_exposure[i] * stress_multiplier[i])。求最小f,使配置首次变为不可行——即低于该阈值时所有对手方都在配额内、达到或超过该阈值时至少一个被击穿:

feasible(f) = all(exposure_i(f) <= cap[i] for i in range(N))

由于 stress_multiplier[i] >= 1feasible(f) 是单调的(前缀 [0, f*) 上为 TRUE、[f*, 1] 上为 FALSE),故在 [0, 1] 上做二分搜索定位 f*。二分在 hi - lo <= tol 时停止,返回 (hi + lo) / 2。哨兵契约(不抛异常):若 N = 0 返回 1.0(恒真);若任一 base_exposure[i] > cap[i] 返回 -1.0(无压时已击穿);若 f = 1.0 仍可行(满压下无击穿)返回 1.0

solution([100.0, 100.0], [200.0, 150.0], [2.0, 2.0], 1e-9) 返回约 0.5。对手方 0:100 * (1 + f) <= 200f <= 1.0。对手方 1:100 * (1 + f) <= 150f <= 0.5。绑定的是索引 1;谓词在 f* = 0.5 处翻转,二分收敛到该点。solution([100.0], [80.0], [2.0], 1e-9) 返回 -1.0:在 f = 0 时敞口已经是 100 > 80,故配置在任何严重度下都不可行——哨兵把答案钉在 -1.0solution([10.0, 20.0], [100.0, 200.0], [1.0, 1.0], 1e-9) 返回 1.0:每个 stress_multiplier[i] == 1.0,故对任何 f 压力后敞口都等于 base,两个 base 都远低于配额——[0, 1] 上恒可行,哨兵返回 1.0

区分形态是对多对手方单调可行性谓词的二分搜索。每个 exposure_i(f) 关于 f 非递减(stress_multiplier[i] >= 1),故各对手方配额约束的 AND 在 [0, 1] 上至多翻转一次——存在唯一阈值 f*。先跑三个哨兵分支(N = 0 -> 1.0;任一 base 已超 cap -> -1.0;满压仍可行 -> 1.0);仅在 f = 0 可行且 f = 1 不可行的结构良好分支才进入二分循环。循环内在 mid = 0.5 * (lo + hi) 处评估谓词:扫描全部 N 个对手方,一旦发现某个击穿配额立即跳出。若可行则 lo = mid,否则 hi = mid。当 hi - lo <= tol 时停止,返回 (hi + lo) / 2。对配额用非严格的 <=,把 exposure_i(f) == cap[i] 留在可行集内——突变成 < 会错处理满压恰好压在配额上的情形(此时答案必须是 1.0,不能严格小于)。每次迭代 O(N),总成本 O(N * log(1/tol))

详见 stubs/stub.py 的函数骨架。

实践背景

信用风险台每日(含日内)会跑覆盖整本对手方簿的压力情景,用于测算资本、设置预警触发器、为交易前的限额检查提供输入。一个典型问题是:参数化压力情景的严重度升到多大时,组合内逐对手方的敞口首次击穿任意一个已配置的逐对手方限额?严重度因子 f 参数化一族连续情景,从 f = 0(不施压、当前簿)到 f = 1(已校准的满压情景,每个对手方的敞口被该情景下的放大因子 stress_multiplier[i] 倍乘)。由于每个逐对手方敞口关于 f 单调非递减、配额约束在对手方间一致施加,逐对手方约束的 AND 是一个教科书式的单调可行性谓词——正是答案空间二分的标准输入形态。阈值 f* 即预警指标:低于 f* 的任何严重度下所有对手方都在限额内;达到或超过 f* 时至少一个被触发。这与到期收益率二分(价格-收益率求根)、IRR 二分(NPV 求根)、隐含波动率二分(Black-Scholes 价格求根)、统一减值二分(单一总额覆盖)、窗口大小二分(滑动窗口计数命中目标)都不同——这是多对手方可行性阈值搜索N 个逐对手方不等式的 AND,关于单一严重度因子单调。

约束条件

  • 1 <= N = len(base_exposure) = len(cap) = len(stress_multiplier) <= 5000;或 N = 0(空数组——哨兵分支返回 1.0)
  • 对所有 i 满足 1e-6 <= base_exposure[i], cap[i] <= 1e9;对所有 i 满足 1.0 <= stress_multiplier[i] <= 100.0;1e-9 <= tol <= 1e-2
  • 输出是谓词 `all(base_exposure[i] * (1 + f * (stress_multiplier[i] - 1)) <= cap[i])` 在 [0, 1] 上从 TRUE 翻转为 FALSE 的最小 f;二分在 `hi - lo <= tol` 时停止并返回 `(hi + lo) / 2`
  • 哨兵契约(不抛异常):N = 0 返回 1.0;任一 base_exposure[i] > cap[i] 返回 -1.0;f = 1.0 仍可行(满压力下无击穿)返回 1.0;其余情形在 [0, 1] 上二分
  • 输出为单个浮点数;比较器为 float,rel_tol = 1e-6、abs_tol = 1e-6(比较器吸收二分结果中由 tol 限定的不确定性)
  • 参考解复杂度:O(N * log(1/tol))——每次谓词评估为 O(N),二分进行 O(log(1/tol)) 次

样例

Case 1 · statement-example: binding cp 1 at f=0.5

输入: [[100,100],[200,150],[2,2],1e-9]

期望: 0.5000000004656613

cp1 绑定:100*(1+f)<=150 ⇒ f<=0.5;阈值 f*=0.5

Case 2 · statement-example: base already over cap returns -1

输入: [[100],[80],[2],1e-9]

期望: -1

f=0 时敞口 100>80,已击穿,返回 -1.0

Case 3 · statement-example: no stress amplification returns 1

输入: [[10,20],[100,200],[1,1],1e-9]

期望: 1

所有 stress_multiplier=1 且 base<cap,恒可行,返回 1.0

最近提交

还没有提交记录。

编码区

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

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

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

Case 1 · statement-example: binding cp 1 at f=0.5

输入: [[100,100],[200,150],[2,2],1e-9]

期望: 0.5000000004656613

cp1 绑定:100*(1+f)<=150 ⇒ f<=0.5;阈值 f*=0.5

Case 2 · statement-example: base already over cap returns -1

输入: [[100],[80],[2],1e-9]

期望: -1

f=0 时敞口 100>80,已击穿,返回 -1.0

Case 3 · statement-example: no stress amplification returns 1

输入: [[10,20],[100,200],[1,1],1e-9]

期望: 1

所有 stress_multiplier=1 且 base<cap,恒可行,返回 1.0