黏性二值仓位策略 —— 含每次切换税与初始状态锚定的最佳 PnL
Sticky Binary-State Strategy — Best PnL With Per-Flip Tax And Initial-State Anchor
开始编码实现 solution(returns: list[float], tau: float, initial_state: int) -> float。交易者在每期收益序列上运行一个黏性二值仓位策略:每期 t ∈ [0, N) 的仓位 s_t 取 1(多头)或 0(空仓);期 t 的已实现 PnL 贡献 = s_t * returns[t],空仓期无论 returns[t] 是正是负都贡献为零。相邻两期之间一旦发生 FLIP(s_{t-1} != s_t),固定支付一次切换税 tau >= 0;维持原状免费。关键之处在于 initial_state 表示**严格在期 0 之前**的仓位状态,从 initial_state 转到 s_0 若两者不同也要支付一次 tau,相同则免费。末期不存在归零税——期 N-1 之后的仓位选哪个能最大化总 PnL 就保留哪个。
返回 sum_t s_t * returns[t] - tau * (#flips) 的最大值,其中 #flips 统计 t = 0, 1, ..., N-1 中所有满足 s_{t-1} != s_t 的过渡(其中 s_{-1} 定义为 initial_state)。
例
solution([0.5, -0.3, 0.4, -0.2, 0.6], 0.1, 0) 返回 1.0。在 initial_state = 0、tau = 0.1 下,多条调度并列最优。一个具体最优为 s = [1, 0, 1, 0, 1]:付一次开仓税切到多头,吃掉 0.5;切回空仓跳过 -0.3;再切到多头吃 0.4;切回空仓跳过 -0.2;再切到多头吃 0.6。共 5 次 FLIP,每次 tau = 0.1、合计 0.5;毛利 = 0.5 + 0.4 + 0.6 = 1.5;净 = 1.0。又如 s = [1, 0, 1, 1, 1],3 次 FLIP 共 0.3,毛利 0.5 + 0.4 + (-0.2) + 0.6 = 1.3,净也是 1.0。多种路径并列在 1.0,DP 递推会自动找到。
实践背景
一个 regime-switching 的执行台在每期的合成收益序列("alpha 序列")上跑一个二值的开/关分配器;翻转主开关——把分配器从开切到关或反之——会触发一次固定的"操作税",这层成本代理了执行摩擦、滑点以及叫醒上游账本的开销。研究主管想知道:在当前 tau 下、在分析窗口起始时该台账实际所处的仓位状态(即 initial_state)锚定下,事后完美择时所能达到的 PnL 上界是多少。该数字以"捕获率"口径给候选信号模型打分:模型若能捕获该上限的 60%,就是相对一个诚实的基准做得不错;而把模型得分相对一个无约束的"零成本切换"幻想去比,会让所有模型看起来都很美。该上限对 tau 高度敏感:tau 增大时最优解退化为"挑一个仓位永不切换",落到收益序列上的 buy-and-hold(或全程空仓);tau -> 0 时塌缩为"对每个正收益吃满",与 initial_state 解耦。initial_state 的依赖很重要——真实台账很少从一张白纸起步,它在前一节交易已经处于多头或空仓中,边界税是真要付的。
实现细节由 stubs/stub.py 提供。
约束条件
- 0 <= N <= 200000,其中 N 为 solution(returns, tau, initial_state) 的 returns 输入长度
- 0.0 <= tau <= 1e9;tau 为有限非负浮点数,仅在每次 FLIP(状态切换)时收取一次
- 每个 returns[i] 为有限浮点数,-1e6 <= returns[i] <= 1e6(每期收益率,**不是**价格)
- initial_state 严格取 0 或 1;它是期 0 之前的仓位状态,选 s_0 != initial_state 收一次 tau,选 s_0 == initial_state 收 0
- 输出为有限浮点数;比较器为 float,rel_tol = 1e-9,abs_tol = 1e-12。空 returns 必须返回 0.0
样例
Case 1 · statement-example: zigzag with tau=0.1 init=0 -> 1.0
输入: [[0.5,-0.3,0.4,-0.2,0.6],0.1,0]
期望: 1
一个具体最优 s=[1,0,1,0,1]:5 次 FLIP × 0.1 = 0.5 切换税,毛利 0.5+0.4+0.6 = 1.5,净 1.0;s=[1,0,1,1,1] 用 3 次 FLIP 也并列得 1.0。
Case 2 · statement-example: tau=0 collapses to sum of positives
输入: [[0.5,-0.3,0.4,-0.2,0.6],0,0]
期望: 1.5
tau=0 时策略退化为对每个正收益持多,答案为 0.5+0.4+0.6 = 1.5,与 initial_state 无关。
Case 3 · statement-example: huge tau collapses to never-flip-after-init
输入: [[0.5,-0.3,0.4,-0.2,0.6],1000000000,1]
期望: 1
tau 极大时 init=1 下永不切换,答案就是 sum(returns) = 0.5-0.3+0.4-0.2+0.6 = 1.0,与全程空仓 0 相比 1.0 更优。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: zigzag with tau=0.1 init=0 -> 1.0
输入: [[0.5,-0.3,0.4,-0.2,0.6],0.1,0]
期望: 1
一个具体最优 s=[1,0,1,0,1]:5 次 FLIP × 0.1 = 0.5 切换税,毛利 0.5+0.4+0.6 = 1.5,净 1.0;s=[1,0,1,1,1] 用 3 次 FLIP 也并列得 1.0。
Case 2 · statement-example: tau=0 collapses to sum of positives
输入: [[0.5,-0.3,0.4,-0.2,0.6],0,0]
期望: 1.5
tau=0 时策略退化为对每个正收益持多,答案为 0.5+0.4+0.6 = 1.5,与 initial_state 无关。
Case 3 · statement-example: huge tau collapses to never-flip-after-init
输入: [[0.5,-0.3,0.4,-0.2,0.6],1000000000,1]
期望: 1
tau 极大时 init=1 下永不切换,答案就是 sum(returns) = 0.5-0.3+0.4-0.2+0.6 = 1.0,与全程空仓 0 相比 1.0 更优。