← 返回编程题库
coding-min-leverage-cap-target-risk中等免费版2000ms未尝试

Calibrating the Minimum Leverage Cap for a Target Risk Budget

Calibrating the Minimum Leverage Cap for a Target Risk Budget

开始编码

风险管理岗负责一本 NN 个资产的持仓 book:每个资产有一个非负的单位波动率 voli0\mathrm{vol}_i \ge 0 和一个带符号权重 wiw_i(正 = 多头,负 = 空头)。账面总风险定义为按毛敞口加权的波动率:

risk=i=1Nwivoli. \text{risk} = \sum_{i=1}^{N} |w_i| \cdot \mathrm{vol}_i.

合规给出每日风险预算 target_risk\text{target\_risk},desk 需要通过单一的逐资产杠杆上限 CC 来落实它:每个毛权重被按 wimin(wi,C)|w_i| \leftarrow \min(|w_i|, C) 收紧后,再把原始符号贴回去。交易员的关切是校准——*「我们至少需要把上限收到多紧,才能让收紧后的组合仍然合规?」* 等价地说,找到使 post-cap 风险仍 \le 预算的最大 CC;那就是「最不严苛的合规上限」,也即合规可以要求的最小杠杆扣减。

实现 solution(vols, weights, target_risk, abs_tol) -> float。返回 CC,使得在执行 wisign(wi)min(wi,C)w_i \leftarrow \mathrm{sign}(w_i) \cdot \min(|w_i|, C) 之后,post-cap 总风险满足 imin(wi,C)volitarget_risk\sum_i \min(|w_i|, C) \cdot \mathrm{vol}_i \le \text{target\_risk},且 CC 收敛到阈值的 abs_tol 邻域内。

post-cap 风险函数

f(C)=i=1Nmin(wi,C)voli f(C) = \sum_{i=1}^{N} \min(|w_i|, C) \cdot \mathrm{vol}_i

CC 上非递减:每一项都是常数与 CC 线性增函数的逐点最小,乘上非负波动率,因此 ffCC 上是非递减的分段线性函数。可行集 {C0:f(C)target_risk}\{C \ge 0 : f(C) \le \text{target\_risk}\} 是左端锚定的区间 [0,C][0, C^\star],校准答案就是右端点 CC^\star。由于判定单调,对 CC二分就能在 O(Nlog(maxwi/abs_tol))O(N \log(\max|w_i| / \text{abs\_tol})) 内找到 CC^\star —— 不需要闭式解,也不会在分段线性的 knee 处出问题。

Edge 情形。target_riskinitial_risk\text{target\_risk} \ge \text{initial\_risk},未收紧的组合已经合规,最大可行上限是 maxiwi\max_i |w_i| —— 任何 \ge 该值的上限都不会改写权重。若 target_risk=0\text{target\_risk} = 0 且初始风险为正,唯一能把每个 wivoli|w_i| \cdot \mathrm{vol}_i 压到 0 的上限是 C=0C = 0。若 target_risk<0\text{target\_risk} < 0 请求不可行,函数抛 ValueError

示例

solution([0.20, 0.15, 0.10], [1.0, -2.0, 3.0], 0.5, 1e-9) 返回约 1.2。初始风险 = 0.2 + 0.3 + 0.3 = 0.8 > 0.5,需要收紧上限。在 C=1.2C=1.2 时第一资产 w=1|w|=1 已被锁在原权重,另两资产还在线性段(1.2<2<31.2 < 2 < 3),f(1.2)=0.21+0.151.2+0.101.2=0.5f(1.2) = 0.2 \cdot 1 + 0.15 \cdot 1.2 + 0.10 \cdot 1.2 = 0.5 恰好等于预算。

solution([0.1, 0.2, 0.3], [1.0, -2.0, 3.0], 100.0, 1e-9) 返回 3.0。初始风险 = 1.4 < 100,未收紧的组合已经合规,最大不绑定的上限就是 max(w)=3\max(|w|) = 3

solution([0.5, 0.5], [1.0, 1.0], 0.0, 1e-9) 返回 0.0target_risk=0\text{target\_risk} = 0 时唯一把每一项压到 0 的上限是 C=0C=0

参考 stubs/stub.py 中的函数骨架。

Practical context

杠杆上限校准是风险团队在策略中途突破预算时第一道伸手的杠杆。比起重跑优化器,他们问一个严格更便宜的问题:*「我们能加的最宽松的逐资产毛敞口上限是多少,使账面回到限额内?」* 答案是 CC 上一维单调判定式的阈值——正是「对答案做二分」最擅长的形状。也可以用 Newton 或区间根求解器去解 f(C)target_risk=0f(C) - \text{target\_risk} = 0,但 ff 在每个 C=wiC = |w_i| 处都有 knee(每越过一个 knee 斜率就掉 voli\mathrm{vol}_i)—— Newton 可能正好在 knee 上停滞,而二分无论答案落在哪儿都按对半收敛。同样的「单调判定 + 二分」模式在 desk 上反复出现:换手率上限校准(让聚合换手率 \le 预算的最宽松上限)、抢仓削减幅度(把 top-N 抢仓评分压回阈值的最小 haircut)、清算 / 净额结算模拟里的 netting-band 选择、以及压力测试约束下的资本缓冲尺寸。每个的 ff 不同,但算法核——可行性判定加上对连续阈值的二分——完全一样,工程收益也一样:在 O(N) 判定上叠 O(log(1/tol)),无参数易碎性,无需闭式解。本题训练这个范式的标准实例:在真金白银的风险约束上对一个杠杆上限做校准,全是 knee,毫无歧义。

约束条件

  • 1 <= N <= 10^4,其中 N = len(vols) = len(weights)
  • 0 <= vols[i] <= 1.0
  • -10 <= weights[i] <= 10
  • target_risk >= 0(target_risk < 0 抛 ValueError)
  • 1e-12 <= abs_tol <= 1e-3
  • Edge:target_risk >= initial_risk → 返回 max(|weights|)(无需收紧上限;合规已成立时给出最大可行上限)
  • Edge:target_risk == 0 且 vols/weights 非全零 → 返回 0.0(唯一能把所有项压到 0 的上限)
  • Edge:vols 全 0 或 weights 全 0 → initial_risk = 0 落入第一条 edge,返回 max(|weights|),权重全 0 时即为 0
  • 浮点比较器:测试中 rel_tol = abs_tol = 1e-6

样例

Case 1 · statement example: 3 vols mixed signs, moderate cap

输入: [[0.2,0.15,0.1],[1,-2,3],0.5,1e-9]

期望: 1.1999999997206032

初始风险 = 0.2*1+0.15*2+0.1*3 = 0.8 > 目标 0.5。f(C) = 0.2*min(1,C) + 0.15*min(2,C) + 0.1*min(3,C)。在 C=1.2 处三项均未触顶(1<1.2 不触顶,第一项保持 0.2;其余两项还在线性段),f(1.2)=0.2+0.18+0.12=0.5 恰好等于预算,C* ≈ 1.2 是满足约束的最大杠杆上限。

Case 2 · two-asset symmetric: cap binds both

输入: [[0.1,0.2],[2,-3],0.4,1e-9]

期望: 1.3333333327900618

初始 0.1*2+0.2*3=0.8。在 C<2 时两项都在线性段,f(C)=(0.1+0.2)C=0.3C,要 ≤0.4 → C≤4/3。bisection 在 [0,3] 上约 32 步把宽度压到 1e-9。

Case 3 · target above initial risk: no capping needed

输入: [[0.1,0.2,0.3],[1,-2,3],100,1e-9]

期望: 3

初始风险 = 0.1+0.4+0.9 = 1.4 ≤ 100,已经合规,无需收紧上限。返回 max(|w|)=3 — 任何 ≥3 的上限都不会改写权重。

最近提交

还没有提交记录。

编码区

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

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

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

Case 1 · statement example: 3 vols mixed signs, moderate cap

输入: [[0.2,0.15,0.1],[1,-2,3],0.5,1e-9]

期望: 1.1999999997206032

初始风险 = 0.2*1+0.15*2+0.1*3 = 0.8 > 目标 0.5。f(C) = 0.2*min(1,C) + 0.15*min(2,C) + 0.1*min(3,C)。在 C=1.2 处三项均未触顶(1<1.2 不触顶,第一项保持 0.2;其余两项还在线性段),f(1.2)=0.2+0.18+0.12=0.5 恰好等于预算,C* ≈ 1.2 是满足约束的最大杠杆上限。

Case 2 · two-asset symmetric: cap binds both

输入: [[0.1,0.2],[2,-3],0.4,1e-9]

期望: 1.3333333327900618

初始 0.1*2+0.2*3=0.8。在 C<2 时两项都在线性段,f(C)=(0.1+0.2)C=0.3C,要 ≤0.4 → C≤4/3。bisection 在 [0,3] 上约 32 步把宽度压到 1e-9。

Case 3 · target above initial risk: no capping needed

输入: [[0.1,0.2,0.3],[1,-2,3],100,1e-9]

期望: 3

初始风险 = 0.1+0.4+0.9 = 1.4 ≤ 100,已经合规,无需收紧上限。返回 max(|w|)=3 — 任何 ≥3 的上限都不会改写权重。