波动稳定段切分 —— 在跨度上限下覆盖收益序列的最少段数
Regime-Stability Segmentation — Fewest Bounded-Spread Runs Over A Return Stream
开始编码实现 solution(returns: list[float], delta_max: float) -> int。给定长度为 N 的每期收益序列与非负跨度上限 delta_max,将其划分为最少数量的连续、不重叠段,使每段的段内跨度 max(段) - min(段) 都不超过 delta_max。返回这一最少段数。
从左到右单遍贪心:维护当前段的 running_max 与 running_min;若并入 returns[i] 会令 max(running_max, returns[i]) - min(running_min, returns[i]) > delta_max,则在 i 处开新段(重置 running_max = running_min = returns[i]);否则把 returns[i] 并入当前段。贪心最优:当前段尽量向右延伸不会逼后续段付出更多切分成本。
示例矩阵:
solution([], 0.10)返回0(空数组用零段覆盖)。solution([0.5], 1.0)返回1(单元素,跨度0 <= 1.0)。solution([0.1, 0.1, 0.1, 0.1], 0.0)返回1(delta_max = 0允许常值段;整段跨度0)。solution([1.0, 2.0, 3.0, 4.0], 0.0)返回4(delta_max = 0且全互异,每元素独立一段)。solution([0.01, 0.02, 0.05, -0.01, -0.02, 0.04, 0.05], 100.0)返回1(cap 极大,整段一段)。
例
solution([0.01, 0.02, 0.05, -0.01, -0.02, 0.04, 0.05], 0.05) 返回 3。从左到右扫描,cap 0.05。下标 0 起首段,running_max = running_min = 0.01。下标 1(0.02):试探跨度 0.02 - 0.01 = 0.01 <= 0.05,并入。下标 2(0.05):跨度 0.05 - 0.01 = 0.04 <= 0.05,并入。下标 3(-0.01):试探跨度 0.05 - (-0.01) = 0.06 > 0.05,切 —— 在下标 3 起新段,running_max = running_min = -0.01。下标 4(-0.02):跨度 (-0.01) - (-0.02) = 0.01,并入。下标 5(0.04):试探跨度 0.04 - (-0.02) = 0.06 > 0.05,切 —— 在下标 5 起新段,running_max = running_min = 0.04。下标 6(0.05):跨度 0.05 - 0.04 = 0.01,并入。共 3 段。
实践背景
研究台为每条回测策略输出一项"波动稳定性"概览指标:扫描日收益序列,统计将其端到端覆盖所需的最少连续有界跨度段数,其中每段的段内跨度(段内日收益的 max - min)必须不超过台子统一容差 delta_max(每个资产类一个值,按典型节内分散度校准)。该计数小,意味着策略大体停留在同一波动率区间;该计数大,意味着日收益分布频繁切换 —— 风险台视为红旗,因为下游风险模型按区间校准,区间频繁切换会失效。"最少段数"的形式化是台子规则:度量本身就是这个计数,因此把每段尽量向右延伸的左到右贪心刚好是风险台想要的。无失败哨兵:任何序列都存在合法划分(最坏情形每元素一段),返回值始终是非负整数。
实现细节由 stubs/stub.py 提供。
约束条件
- 0 <= N <= 5000,其中 N 为 solution(returns, delta_max) 的 returns 输入长度
- 0 <= delta_max <= 2e6,单段允许的最大跨度(任一连续段内 `max - min`)
- 每个 returns[i] 为有限浮点数,-1e6 <= returns[i] <= 1e6(**每期收益率**,不是价格)
- 段合法当且仅当 `max(段) - min(段) <= delta_max`(含等号);切分触发条件为严格 `new_max - new_min > delta_max`(不引入任何 epsilon 容差)
- 返回类型为 int。划分必须**覆盖**整个数组 —— `[0, N)` 中每个下标恰属于一个段,段间连续不重叠。空 returns 返回 0;单元素返回 1;无失败哨兵(答案恒为非负整数)
样例
Case 1 · statement-example: spread cap forces 3 runs
输入: [[0.01,0.02,0.05,-0.01,-0.02,0.04,0.05],0.05]
期望: 3
依次扫描,合并到 0.05 时跨度 0.04<=0.05;遇 -0.01 跨度 0.06>0.05 切;再遇 0.04 跨度 0.06>0.05 切;共 3 段。
Case 2 · statement-example: empty input returns 0
输入: [[],0.1]
期望: 0
空数组无任何元素,按零段覆盖,返回 0。
Case 3 · statement-example: single element returns 1
输入: [[0.5],1]
期望: 1
单元素跨度 0<=delta_max,构成一段。
Case 4 · statement-example: delta_max=0 with all-equal cluster returns 1
输入: [[0.1,0.1,0.1,0.1],0]
期望: 1
所有元素相等,整段跨度 0<=0;单段。
Case 5 · statement-example: delta_max=0 strictly distinct returns N
输入: [[1,2,3,4],0]
期望: 4
delta_max=0 强制每段为常值;元素互不相等,必须每元素一段,返回 4。
Case 6 · statement-example: huge delta_max collapses to 1 run
输入: [[0.01,0.02,0.05,-0.01,-0.02,0.04,0.05],100]
期望: 1
整体最大-最小=0.07<=100,整段一段。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: spread cap forces 3 runs
输入: [[0.01,0.02,0.05,-0.01,-0.02,0.04,0.05],0.05]
期望: 3
依次扫描,合并到 0.05 时跨度 0.04<=0.05;遇 -0.01 跨度 0.06>0.05 切;再遇 0.04 跨度 0.06>0.05 切;共 3 段。
Case 2 · statement-example: empty input returns 0
输入: [[],0.1]
期望: 0
空数组无任何元素,按零段覆盖,返回 0。
Case 3 · statement-example: single element returns 1
输入: [[0.5],1]
期望: 1
单元素跨度 0<=delta_max,构成一段。
Case 4 · statement-example: delta_max=0 with all-equal cluster returns 1
输入: [[0.1,0.1,0.1,0.1],0]
期望: 1
所有元素相等,整段跨度 0<=0;单段。
Case 5 · statement-example: delta_max=0 strictly distinct returns N
输入: [[1,2,3,4],0]
期望: 4
delta_max=0 强制每段为常值;元素互不相等,必须每元素一段,返回 4。
Case 6 · statement-example: huge delta_max collapses to 1 run
输入: [[0.01,0.02,0.05,-0.01,-0.02,0.04,0.05],100]
期望: 1
整体最大-最小=0.07<=100,整段一段。