← 返回编程题库
coding-min-slippage-cutoff-meet-target-sum中等免费版2000ms未尝试

满足目标累计绝对加权滑点的最小截断阈值:单调谓词下的二分搜索

Smallest Slippage Cutoff Meeting a Target Absolute Weighted Cost via Bisection

开始编码

实现 solution(slippage_bps: list[float], notional: list[float], target_sum: float, tol: float) -> float。一个交易员在复盘当日的滑点磁带:第 i 笔成交(共 N = len(slippage_bps) 笔)的每笔滑点为 slippage_bps[i],单位为基点(带符号:负数代表价格改进,正数代表不利成交),notional[i] > 0 是该笔成交的名义权重。"过滤截断阈值" T >= 0 把 trade i 纳入筛入集合当且仅当 abs(slippage_bps[i]) <= T。求最小T,使筛入集合的累计绝对加权滑点成本达到目标预算:

partial_cost(T) = sum(abs(slippage_bps[i]) * notional[i] for i in kept(T)) >= target_sum

其中 kept(T) = {i : abs(slippage_bps[i]) <= T}。每笔贡献 abs(slippage_bps[i]) * notional[i] 非负,故 partial_cost 关于 T 单调非减,谓词在 [0, T_max] 上为 FALSE 然后 TRUE 形态,T_max = max(abs(slippage_bps[i]))。在 [lo=0, hi=T_max] 上二分,维持不变量 predicate(lo) 为 FALSE、predicate(hi) 为 TRUE,缩窄到 hi - lo <= tol 后返回 hi。哨兵契约(不抛异常):若 partial_cost(T_max) < target_sum(即便保留全部 trade 仍达不到目标),返回 -1.0。同样的 -1.0 哨兵适用于空 trade 列表、长度不匹配、非正或非有限的 notional、非有限的 slippage、非有限的 target、非法的 tol。

solution([1.0, 2.0, 3.0], [10.0, 10.0, 10.0], 30.0, 1e-9) 返回 2.0tol 容差内)。每笔的绝对加权贡献分别是 1*10 = 102*10 = 203*10 = 30。沿 T 上行:T = 0 时筛入集合为空,partial_cost = 0 < 30T = 1.0 仅留首笔,partial_cost = 10 < 30T = 2.0 时第 0、1 笔被筛入(绝对滑点 12<= 2),partial_cost = 10 + 20 = 30 >= 30 —— 首次可行。所以满足目标的最小 T 恰为 2.0solution([1.0, 2.0, 3.0], [10.0, 10.0, 10.0], 100.0, 1e-9) 返回 -1.0:即便 T = 3.0 全本簿贡献 10 + 20 + 30 = 60 < 100,无可行截断 —— 哨兵把答案钉在 -1.0solution([], [], 1.0, 1e-9) 同样返回 -1.0:无 trade 可纳入,筛入集合恒为空,partial_cost = 0 < 1,触发哨兵。

区分形态是**对浮点截断阈值 T 在 FALSE-然后-TRUE 谓词上做二分**。T 增大时筛入集合单调扩张(一旦 T 越过某 trade 的绝对滑点,该 trade 永不离开),而每笔贡献 abs(slippage_bps[i]) * notional[i] 非负——故 partial_cost(T) 关于 T 单调非减,predicate(T) = partial_cost(T) >= target_sum[T*, T_max] 后缀上为 TRUE。维持不变量 predicate(lo) 为 FALSE、predicate(hi) 为 TRUE,初始 lo = 0hi = T_max = max(abs(slippage_bps[i])),二分到 hi - lo <= tol 返回 hi。请优先走哨兵分支:partial_cost(T_max) < target_sum -> -1.0、非法输入(空列表、长度不匹配、非正或非有限的 notional、非有限的 slippage、非有限的 target、非法 tol-> -1.0。直接以步长 tol[0, T_max] 上做网格扫描需评估谓词 T_max / tol 次(最坏达 1e8)—— 在 N = 5000 时 TLE。聚合使用 abs(slippage_bps[i]) 而非带符号值,是因为 TCA 解读是累计绝对滑点成本(非负预算);若用带符号贡献,后续负贡献会抵消之前的可行性,破坏单调性、二分将不再是正确工具。这与 coding-min-margin-haircut-bisect(对单一总和的 haircut,单调递减谓词,求最大 h)和 coding-implied-vol-bisection(在 Black-Scholes 价格曲线上求根)有别——这是阈值搜索:找最小的 T,使一个是/否谓词首次回答"是"。

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

实践背景

本题是一个简化版的交易成本分析(TCA)调参器:日终交易桌复盘当日每笔成交的滑点磁带,希望识别"鲁棒核心"——即那些执行质量足以撑起目标累计绝对加权滑点预算的成交。过滤截断阈值 T 拒绝绝对滑点超过 T 的成交(疑似离群点)、保留其余;满足"筛入集合累计绝对加权成本 >= 预算"的最小 T 回答了"我能保证我留存的簿累积到目标绝对滑点成本的最紧质量门槛是什么?"答案直接喂给报价质量报告、经纪商打分卡和日内执行质量看板。闭式做法(按 abs(slippage) 排序后扫前缀和)能在 O(N log N) 内解决,但生产工具背后是不透明的筛入集合评估器(集中度限制、经纪商分级权重、跨场所平滑),它关于 T 单调但无解析逆——所以单调谓词下的二分才是承重的算法原语。本题刻意用最简的聚合(朴素绝对加权和)来锁定算法形态:谓词方向(FALSE 然后 TRUE)、不可达目标的哨兵(-1.0)、以 tol 驱动的终止条件。这与到期收益率(在价格-收益率曲线上求根)和 IRR(在 NPV 上求根)有别——本题是阈值搜索:找最小的 T,使一个是/否谓词首次回答"是"。

约束条件

  • 0 <= len(slippage_bps) <= 5000;len(slippage_bps) == len(notional);每个 slippage_bps[i] 为有限浮点数(带符号,|slippage_bps[i]| <= 1e6);每个 notional[i] 为有限正浮点数(notional[i] > 0 且 notional[i] <= 1e9);target_sum 为有限浮点数,典型情形 0 < target_sum <= 1e15(target_sum <= 0 良定义且可能返回 0.0);tol 为有限浮点数,tol ∈ [1e-9, 1e-2]
  • 输出是最小的浮点阈值 T,T ∈ [0.0, T_max],满足 sum(abs(slippage_bps[i]) * notional[i] for i in kept(T)) >= target_sum,其中 kept(T) = {i : abs(slippage_bps[i]) <= T}、T_max = max(abs(slippage_bps[i]));若 target_sum 在 T = T_max 时仍不可达,返回哨兵 -1.0
  • 哨兵契约(不抛异常):slippage_bps 为空 -> -1.0;len(slippage_bps) != len(notional) -> -1.0;任一非有限或非正的 notional[i] -> -1.0;任一非有限的 slippage_bps[i] -> -1.0;非有限的 target_sum -> -1.0;tol <= 0 或非有限 -> -1.0;T_max 处的 partial_cost 仍低于目标 -> -1.0
  • 输出为单个浮点数;比较器为 float,rel_tol = 1e-6、abs_tol = 1e-6(二分以 hi - lo <= tol 为终止条件,比较器需吸收 tol 量级的容差);-1.0 哨兵以精确相等比较
  • 参考解复杂度:O(N log(T_max / tol)),其中 N = len(slippage_bps);每次谓词求值 O(N),二分轮数 O(log(T_max / tol))

样例

Case 1 · statement-example: smallest cutoff to hit target absolute weighted sum

输入: [[1,2,3],[10,10,10],30,1e-9]

期望: 2.0000000002328306

取阈值 T=2.0 时筛入 |slippage|<=2 的两笔,累计绝对加权滑点 1*10+2*10=30 恰好达标;T<2 时只留首笔贡献 10 不达标

Case 2 · statement-example: target unreachable returns sentinel

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

期望: -1

全部 trade 的累计绝对加权滑点上限为 60 (10+20+30),低于目标 100,无可行 T,返回 -1.0

Case 3 · statement-example: empty trade list returns sentinel

输入: [[],[],1,1e-9]

期望: -1

没有任何 trade 可以被纳入筛选集合,partial_cost 恒为 0 < 1,返回 -1.0

最近提交

还没有提交记录。

编码区

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

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

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

Case 1 · statement-example: smallest cutoff to hit target absolute weighted sum

输入: [[1,2,3],[10,10,10],30,1e-9]

期望: 2.0000000002328306

取阈值 T=2.0 时筛入 |slippage|<=2 的两笔,累计绝对加权滑点 1*10+2*10=30 恰好达标;T<2 时只留首笔贡献 10 不达标

Case 2 · statement-example: target unreachable returns sentinel

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

期望: -1

全部 trade 的累计绝对加权滑点上限为 60 (10+20+30),低于目标 100,无可行 T,返回 -1.0

Case 3 · statement-example: empty trade list returns sentinel

输入: [[],[],1,1e-9]

期望: -1

没有任何 trade 可以被纳入筛选集合,partial_cost 恒为 0 < 1,返回 -1.0