流动性覆盖率:HQLA、流入上限与净流出地板
Liquidity Coverage Ratio: HQLA, Inflow Cap, and Net-Outflow Floor
开始编码实现 solution(hqla: list[float], hqla_haircut: list[float], outflows: list[float], outflow_rates: list[float], inflows: list[float], inflow_rates: list[float]) -> float。资金部需要每日的 Basel III 流动性覆盖率(LCR)。六个输入分为三对独立的 (value, rate)——hqla 与其 haircut、outflows 与压力 run-off 利率、inflows 与 recognised 利率。每对长度相等、三对之间长度独立。所有 rate 输入都是 [0.0, 1.0] 区间内的小数。
输出 LCR 由如下可观测公式定义:
- HQLA 扣减后合计:
hqla_net = sum_i hqla[i] * (1 - hqla_haircut[i])。 - 毛压力流出:
gross_out = sum_i outflows[i] * outflow_rates[i]。 - 毛 recognised 流入:
gross_in = sum_i inflows[i] * inflow_rates[i]。 - 封顶+地板后的净流出:
floor_out = max(gross_out - min(gross_in, 0.75 * gross_out), 0.25 * gross_out)。内层min是 Basel III 75% 流入封顶;外层max是 25% 净流出地板。 - 最终 LCR:
floor_out > 0时LCR = hqla_net / floor_out;floor_out == 0且hqla_net > 0返回float('inf');floor_out == 0且hqla_net == 0返回float('nan')。
例
solution([1000.0, 500.0, 200.0], [0.0, 0.0, 0.5], [800.0, 1200.0], [0.05, 0.40], [100.0, 200.0], [1.0, 0.5]) 返回 5.0。该行持有三块 HQLA:1000 现金与 500 Level-1 政府债,haircut 均为 0.0,再加 200 的 Level-2 公司债,haircut 为 0.5。故 hqla_net = 1000*1 + 500*1 + 200*0.5 = 1600。压力流出:零售存款 800 走 0.05、批发资金 1200 走 0.40,得 gross_out = 40 + 480 = 520。recognised 流入:抵押 100 走 1.0、信用 200 走 0.5,得 gross_in = 100 + 100 = 200。流入封顶检查:0.75 * 520 = 390、gross_in = 200 < 390,故 capped_in = 200(封顶未触发)。net_out = 520 - 200 = 320。地板检查:0.25 * 520 = 130、320 > 130,故 floor_out = 320(地板未触发)。LCR = 1600 / 320 = 5.0——远高于 1.0 的最低线。
一个封顶真正触发的算例:solution([100.0], [0.0], [1000.0], [0.5], [1000.0], [0.6])。此时 hqla_net = 100、gross_out = 500、gross_in = 600。原始流入 600 超过 0.75 * 500 = 375,故 capped_in = 375(封顶生效——银行不能把全部 600 当作抵消)。net_out = 500 - 375 = 125。地板:0.25 * 500 = 125、net_out = 125,故 floor_out = 125。LCR = 100 / 125 = 0.8——低于 1.0 监管最低线。
封顶与地板的代数关系:在约束区间内(所有数值、利率非负)时,封顶生效(即 gross_in > 0.75 * gross_out)必然意味着未钳的 gross_out - gross_in < 0.25 * gross_out,地板会一路把 floor_out 钳到 0.25 * gross_out,无论是否先施加封顶都一样。封顶与地板联合保证 gross_out > 0 时 floor_out >= 0.25 * gross_out。合同只由上面给出的最终输出公式定义——实现者可以用任何代数等价的路径计算 floor_out。25% 净流出地板才是真正起鉴别作用的硬规则:它阻止 LCR 在流入恰好与流出抵消时返回 inf。
边界:hqla_net > 0 而无流出时返回 float('inf')(完全覆盖、无需求);全零返回 float('nan')(0/0)。三对中任意一对为空时该对求和贡献 0.0、永不抛错。
实现细节由 stubs/stub.py 提供。
实践背景
Basel III 监管要求每家银行每日报送流动性覆盖率,衡量优质流动资产对 30 天压力净流出的覆盖程度。监管最低线为 LCR >= 1.0(100%)。银行向审慎监管者上报 LCR 数字;持续低于 1.0 会触发逐级升级的监管行动。标准公式为 LCR = HQLA_after_haircut / max(净 30 天流出, 毛 30 天流出 × 25%),其中 净流出 = 毛流出 - min(毛流入, 毛流出 × 75%)。75% 流入封顶与 25% 净流出地板是 Basel III LCR 条文里明文写下的反"做账"规则——没有封顶,银行可以把大量在压力事件下其实根本不会到账的 recognised 流入凑上去,把 LCR 报得很高;没有地板,流入恰好与流出抵消的银行可以报出 LCR = inf,即便它仍然需要 HQLA 来撑住毛融资曲线。资金部在每日盘后从监管流动性数据仓库里跑这套聚合:HQLA 类别(Level-1 现金、Level-1 政府债、Level-2A covered bond、Level-2B 股权)各自带 Basel 规定的 haircut;流出类别(零售存款、operational 存款、批发资金)带 Basel 规定的 run-off;流入类别(抵押放款应收、零售对手方应收)带 recognised 利率。本函数输出的就是当日 LCR 数字,会接到监管流动性报表与管理层内部流动性看板上。一遍线性扫描——三段独立点积加一次常数比——就是这套聚合的标准模式:三段求和之间无数据依赖,工业实现可以并行算,但简单顺序写法对百量级类别就足够快。
约束条件
- 0 <= len(hqla) == len(hqla_haircut) <= 100
- 0 <= len(outflows) == len(outflow_rates) <= 100
- 0 <= len(inflows) == len(inflow_rates) <= 100
- 0.0 <= hqla[i], outflows[i], inflows[i] <= 1e9 且 0.0 <= hqla_haircut[i], outflow_rates[i], inflow_rates[i] <= 1.0
- 输出为非负 float 或 float('inf')(无流出且 HQLA > 0)或 float('nan')(全零),float 比较器使用 rel_tol=1e-9, abs_tol=1e-9
样例
Case 1 · statement-example: bank with mixed HQLA and uncapped inflows yields LCR 5.0
输入: [[1000,500,200],[0,0,0.5],[800,1200],[0.05,0.4],[100,200],[1,0.5]]
期望: 5
hqla_net=1600;gross_out=520;gross_in=200<390 故 capped_in=200;net_out=320>130 故 floor_out=320;LCR=5.0。
Case 2 · statement-example: inflow cap triggers, LCR 0.8 below regulatory minimum
输入: [[100],[0],[1000],[0.5],[1000],[0.6]]
期望: 0.8
hqla_net=100;gross_out=500;gross_in=600 超过 0.75*500=375 故 capped_in=375;net_out=125;floor_out=max(125,125)=125;LCR=0.8。
Case 3 · visible: all three input pairs empty returns nan sentinel
输入: [[],[],[],[],[],[]]
期望: "NaN"
全空输入:三段求和均为 0;floor_out=0 且 hqla_net=0,0/0 返回 float('nan')。
Case 4 · visible: HQLA only, no outflows, returns inf sentinel
输入: [[100,50],[0,0.2],[],[],[],[]]
期望: "Infinity"
hqla_net=100+40=140;gross_out=0;floor_out=0 且 hqla_net>0 返回 float('inf')。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: bank with mixed HQLA and uncapped inflows yields LCR 5.0
输入: [[1000,500,200],[0,0,0.5],[800,1200],[0.05,0.4],[100,200],[1,0.5]]
期望: 5
hqla_net=1600;gross_out=520;gross_in=200<390 故 capped_in=200;net_out=320>130 故 floor_out=320;LCR=5.0。
Case 2 · statement-example: inflow cap triggers, LCR 0.8 below regulatory minimum
输入: [[100],[0],[1000],[0.5],[1000],[0.6]]
期望: 0.8
hqla_net=100;gross_out=500;gross_in=600 超过 0.75*500=375 故 capped_in=375;net_out=125;floor_out=max(125,125)=125;LCR=0.8。
Case 3 · visible: all three input pairs empty returns nan sentinel
输入: [[],[],[],[],[],[]]
期望: "NaN"
全空输入:三段求和均为 0;floor_out=0 且 hqla_net=0,0/0 返回 float('nan')。
Case 4 · visible: HQLA only, no outflows, returns inf sentinel
输入: [[100,50],[0,0.2],[],[],[],[]]
期望: "Infinity"
hqla_net=100+40=140;gross_out=0;floor_out=0 且 hqla_net>0 返回 float('inf')。