累计 PnL 回撤告警:超过阈值的水下时刻下标
Cumulative PnL Drawdown Alert: Sorted Indices Underwater Beyond Threshold
开始编码实现 solution(returns: list[float], dd_threshold: float) -> list[int]。给定一段长度为 N 的逐期收益流 returns 和一个严格正的回撤阈值 dd_threshold,构造累计 PnL 路径 P[i] = sum(returns[0..i]) 与运行峰值 M[i] = max(P[0], ..., P[i])(含 i 的峰值)。返回所有满足回撤深度 M[i] - P[i] 严格大于 dd_threshold 的下标 i,并按升序排序——也就是累计 PnL 从运行峰值跌下超过 dd_threshold 的那些时刻。
示例:solution([1.0, -2.0, 1.0, -3.0, 5.0], 1.5) 返回 [1, 3]。逐步推导:P = [1, -1, 0, -3, 2],M = [1, 1, 1, 1, 2],回撤深度 M - P = [0, 2, 1, 4, 0]。深度严格大于 1.5 的下标是 1(深度 2)与 3(深度 4);下标 2 的深度为 1,未超过阈值;下标 4 处刚好刷新到新高,深度为 0。
边界情况必须严格处理:solution([], 0.5) 返回 [];当 dd_threshold <= 0 时抛出 ValueError。阈值上的等号不算告警:solution([1.0, -1.0], 1.0) 返回 [],因为下标 1 的回撤深度恰好为 1.0,而 1.0 > 1.0 不成立。单调递增的累计路径不产生任何告警;单调递减的路径从首次回撤超阈的那一下标起持续告警;先深陷水下、后续完全反弹刷新峰值的路径只在水下区间产生告警,刷新新高之后停止告警。
每一步都重算 max(P[0..i]) 的 O(N^2) 写法在当前约束下其实仍能挤进 2s 预算——本题的区分点在正确性而非时间复杂度:错误的 tie-break(用 >= 而不是 >)、漏掉峰值的"含 i"语义、或者把 P[i] 直接和 -dd_threshold 比较,都会被隐藏用例命中。预期解法是单趟线性扫描:用两个标量分别保存 cum 与 peak,仅当 peak - cum > dd_threshold 严格成立时才向输出列表追加下标。
实现细节由 stubs/stub.py 提供。
实践背景
线上"回撤告警"面板会盯住策略已实现的累计 PnL,一旦权益从运行高水位掉下超过某个可配置阈值,就向风控发出提示。被标记的时间戳列表是风控复盘"何时进入告警状态"的审计轨迹——它既参与"是否被一笔大单一次打穿、还是被慢慢磨损"的事后归因,也用于"水下自动减仓"等策略约束。生产里有两个合约细节非常容易踩坑。第一,运行峰值是包含当前 bar 的峰值——若用"上一根 bar 的峰值"来比较,会出现 off-by-one 伪迹:刚刷新新高的 bar 漏标,或者刚好打穿前高的 bar 被双标。第二,比较是严格大于:组合经理把阈值配成"5%"时,意思是回撤深度刚好打到 5% 还不构成告警、再往下走一格才算;如果用 >=,每次回撤恰好等于阈值(在离散网格上很常见)都会触发误报,把告警通道刷屏。
约束条件
- 0 <= N <= 6000,其中 N 为 solution(returns, dd_threshold) 的输入长度
- 每个 returns[i] 为 [-1000.0, 1000.0] 区间内的有限 float
- dd_threshold 为严格正的 float(> 0);非正的 dd_threshold 抛出 ValueError
- 空输入(且 dd_threshold 合法)返回空列表 []
- 输出为按升序排列的 int 下标列表;使用精确比对
样例
Case 1 · statement-example: drawdown breach in middle
输入: [[1,-2,1,-3,5],1.5]
期望: [1,3]
P=[1,-1,0,-3,2], M=[1,1,1,1,2], 回撤深度=[0,2,1,4,0],>1.5 的下标为 1 和 3。
Case 2 · visible: empty input returns []
输入: [[],0.5]
期望: []
空输入直接返回空列表。
Case 3 · visible: tie on threshold (strict >) NOT flagged
输入: [[1,-1],1]
期望: []
P=[1,0], M=[1,1], 回撤=[0,1];阈值为 1.0,严格大于不成立,故空。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: drawdown breach in middle
输入: [[1,-2,1,-3,5],1.5]
期望: [1,3]
P=[1,-1,0,-3,2], M=[1,1,1,1,2], 回撤深度=[0,2,1,4,0],>1.5 的下标为 1 和 3。
Case 2 · visible: empty input returns []
输入: [[],0.5]
期望: []
空输入直接返回空列表。
Case 3 · visible: tie on threshold (strict >) NOT flagged
输入: [[1,-1],1]
期望: []
P=[1,0], M=[1,1], 回撤=[0,1];阈值为 1.0,严格大于不成立,故空。