← 返回编程题库
coding-max-profit-bounded-drawdown困难免费版2000ms未尝试

限定回撤下的最优持仓收益

Maximum Profit Over Bounded-Drawdown Window

开始编码

某只股票的日线价格序列已经给到你,作为风控严格的策略 PM,你愿意接受的单笔持仓最大瞬时回撤max_drawdown——也就是说,从你买入那天起,到你某天卖出之前的任何时刻,从已实现的持仓峰值往下跌的幅度都不能超过 max_drawdown,否则你的止损线就会被触发。请在这一硬约束下,找出理论上可以拿到的最高单笔收益 prices[sell] − prices[buy]

形式化地:实现 solution(prices: list[float], max_drawdown: float) -> float,对所有满足下述条件的 (buy, sell) 对(其中 0 ≤ buy ≤ sell < len(prices)),返回 prices[sell] − prices[buy] 的最大值;条件是对每个 k ∈ [buy, sell],都有 max(prices[buy..k]) − prices[k] ≤ max_drawdown。如果做不到正收益(例如序列单调下跌,或回撤约束太紧),就返回 0.0,相当于不开仓。

举个例子,solution([10, 12, 9, 14, 16, 11], 3.0) 应该返回 7.0

  • 如果 buy=0sell=4,持仓期间 running peak 走的是 10→12→12→14→16,对应的瞬时回撤分别是 0, 0, 3, 0, 0,最大值 3 正好踩到 max_drawdown=3 的红线。可以接受,收益 16 − 10 = 6
  • 如果换成 buy=2sell=4:running peak 9→14→16,回撤 0, 0, 0,没有触发止损;收益 16 − 9 = 7。这是更优解。
  • 如果 sell=5,无论从哪天买,从 16 跌到 11 已经是 5 的回撤,超过 3,不能持有到 5。

朴素的 O(n²) 双层循环对小输入足够,但当 n 接近 10⁵ 时会超时。请考虑用两条单调双端队列——一条管理窗口最大值(用于约束检查),一条管理窗口最小值(用于卖点对应的最优买点)——把时间压到 O(n)

约束条件

  • 0 ≤ len(prices) ≤ 100000
  • 0 < prices[i] ≤ 10⁶
  • 0.0 ≤ max_drawdown ≤ 10⁶(绝对价差,不是百分比)
  • 若 prices 为空,返回 0.0
  • 若没有任何持仓窗口能赚钱,返回 0.0(不交易就是 0 收益)
  • 返回值是浮点数,允许 1e-6 的相对误差

样例

Case 1 · two valid windows, peak triggers stop loss at end

输入: [[10,12,9,14,16,11],3]

期望: 7

选 buy=2、sell=4,持仓价格走 9→14→16,回撤始终为 0,盈利 16−9=7。若坚持持有到第 5 天 (price=11),从 16 跌到 11 已经是 5 单位回撤,超过 max_drawdown=3,触发止损。

Case 2 · monotone uptrend, drawdown never tested

输入: [[1,3,4,9,11],0]

期望: 10

价格单调上行,每一时刻的瞬时回撤都是 0,所以任何持仓窗口都合法。最优策略是 buy=0、sell=4,盈利 11−1=10。

最近提交

还没有提交记录。

编码区

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

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

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

Case 1 · two valid windows, peak triggers stop loss at end

输入: [[10,12,9,14,16,11],3]

期望: 7

选 buy=2、sell=4,持仓价格走 9→14→16,回撤始终为 0,盈利 16−9=7。若坚持持有到第 5 天 (price=11),从 16 跌到 11 已经是 5 单位回撤,超过 max_drawdown=3,触发止损。

Case 2 · monotone uptrend, drawdown never tested

输入: [[1,3,4,9,11],0]

期望: 10

价格单调上行,每一时刻的瞬时回撤都是 0,所以任何持仓窗口都合法。最优策略是 buy=0、sell=4,盈利 11−1=10。