仓位区间治理:保持净仓在 [-L, +L] 内所需的最少日终归零次数
Position-Band Governance: Minimum Flatten-Resets to Stay Inside [-L, +L]
开始编码实现 solution(deltas: list[float], L: float) -> int。某交易台的净仓 pos 起始为 0.0。对于 0..N-1 每个周期 i,周期内按以下顺序选择两种转移之一:
- 先归零再下单(计
1):先pos := 0.0,再pos += deltas[i]。周期收盘pos = deltas[i]。 - 不归零,仅下单(计
0):pos += deltas[i]。周期收盘pos = pos_prev + deltas[i]。
每个周期的收盘 pos 都必须满足 -L <= pos <= +L。返回所有周期的最小总代价(归零次数)。
不可行性(单笔预筛)。 由于周期 i 的归零转移直接以 pos = deltas[i] 收盘,时刻表能让周期 i 收盘在区间内的必要条件是 |deltas[i]| <= L;若 |deltas[i]| > L,连归零选择都越界,该周期没有任何可行选项——整张时刻表被宣告不可行、返回 -1。(这对齐了交易台的标准 pre-trade 规则:任何单笔大于半宽 L 的单据都会被风控网关拒收,根本不会进入 running-pos 的环节。)一旦遇到第一个这样的 i 立刻返回 -1。空 deltas 返回 0。L = 0.0 时区间塌缩为 {0.0},任何非零 delta 不可行(返回 -1);所有 delta 全为 0 则返回 0。
例
solution([0.6, 0.6, 0.6, -0.9, 0.6], 1.0) 返回 2。
| 周期 | pos_prev | deltas[i] | 不归零收盘 | 归零收盘 | 选择 | pos_post |
|--|--|--|--|--|--|--|
| 0 | 0.0 | 0.6 | 0.6(在区间) | 0.6(在区间) | 不归零 | 0.6 |
| 1 | 0.6 | 0.6 | 1.2(出区间) | 0.6(在区间) | 归零(累计 1) | 0.6 |
| 2 | 0.6 | 0.6 | 1.2(出区间) | 0.6(在区间) | 归零(累计 2) | 0.6 |
| 3 | 0.6 | -0.9 | -0.3(在区间) | -0.9(在区间) | 不归零 | -0.3 |
| 4 | -0.3 | 0.6 | 0.3(在区间) | 0.6(在区间) | 不归零 | 0.3 |
合计 2 次归零。周期 0、3、4 的不归零收盘已落在区间,故计 0;周期 1、2 的不归零收盘越界,必须归零,每次计 1。
朴素的"凡是非零 delta 周期都归零"会过补(本例给 5)。朴素的"等收盘越界再归零"违反契约:该周期已经以越界状态收盘。预期解法是单次自左向右扫描:先检查 |deltas[i]| > L(出现则立即返回 -1),再要么保持累加 pos、要么在不归零收盘越界时计数 +1 并把 pos 重锚为 deltas[i](等价于归零选择)。整段闭式 O(N)——无 DP、无双指针。
实现细节由 stubs/stub.py 提供。
实践背景
某交易台对其日内净仓施加了一条自定的双侧区间 [-L, +L]——一条软风险限额,对齐内部仓位上限。台子的风控网关另外硬性要求每笔单据 |单笔| <= L(任何单笔大于半宽 L 的单据都会被网关层 pre-trade 检查拒收,必须先拆单再提交)。给定下一交易日各周期的有符号流量预测,风控团队的提问是"为了让每个周期收盘的累积净仓都落在区间内,至少需要多少次周期内归零(在下一笔交易落账之前与对冲对手方完全平账的运营事件)?"每次归零都有运营成本:对冲运营人员时间、对账记录、内部审批。每个交易日盘后对下一交易日的预测路径调用一次 solution(deltas, L),就能给到一份"归零频次"预算用于安排下一交易日对冲运营排班;返回 -1 表示预测时刻表中至少有一笔单据会被网关拒收——交易台必须或者拆单、或者放宽 L、或者人工预先平滑流量,再行计数。
约束条件
- 0 <= len(deltas) <= 5000;每个 deltas[i] 为浮点数,|deltas[i]| <= 1e6
- 0.0 <= L <= 1e9(区间半宽为非负浮点数;允许 L = 0.0,此时除非所有 delta 都为 0.0 否则返回 -1)
- 每个周期 i 按顺序执行两阶段:(1) 可选执行一次将 pos 置 0 的归零(计 1);(2) 该笔交易落账(pos += deltas[i])。该周期收盘 pos 必须落在 [-L, +L] 内
- 单笔预筛:若任意 |deltas[i]| > L,时刻表被宣告不可行(周期 i 的归零选择会以 pos = deltas[i](自身越界)收盘,所以即便允许任意多次归零,周期 i 也无法在区间内收盘);返回 -1
- 输出为 int:最少归零次数,不可行时返回 -1 哨兵;使用精确比对
样例
Case 1 · statement-example: deltas [0.6,0.6,0.6,-0.9,0.6] L=1.0 needs 2 resets
输入: [[0.6,0.6,0.6,-0.9,0.6],1]
期望: 2
周期 1 与周期 2 临时落账各为 1.2,超出 [-1,1],每次需要一次归零,重锚为该笔 delta=0.6;周期 3、4 自然落入区间。共 2 次。
Case 2 · visible: empty deltas returns 0
输入: [[],5]
期望: 0
空输入直接返回 0。
Case 3 · visible: single trade overshoots band returns -1 sentinel
输入: [[2.5],1]
期望: -1
|2.5| > 1.0,单笔超区间,即使前后各归零仍越界,返回 -1。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: deltas [0.6,0.6,0.6,-0.9,0.6] L=1.0 needs 2 resets
输入: [[0.6,0.6,0.6,-0.9,0.6],1]
期望: 2
周期 1 与周期 2 临时落账各为 1.2,超出 [-1,1],每次需要一次归零,重锚为该笔 delta=0.6;周期 3、4 自然落入区间。共 2 次。
Case 2 · visible: empty deltas returns 0
输入: [[],5]
期望: 0
空输入直接返回 0。
Case 3 · visible: single trade overshoots band returns -1 sentinel
输入: [[2.5],1]
期望: -1
|2.5| > 1.0,单笔超区间,即使前后各归零仍越界,返回 -1。