单名集中度限制下的整股组合分配
Whole-Share Portfolio Allocator under a Single-Name Cap
开始编码某小盘股组合经理在严格的单名集中度上限下管理整股账户:任一截面上,每只名字至多持有一股。给定整数的现金预算与候选名字清单——每只候选含整数的整股成本与持有一股至下一截面的绝对美元期望 P&L——挑选一个不超过预算且总期望 P&L 最大的子集。与连续型的均值-方差配置不同,这里的最小交易单位是整股,因此问题完全离散化。
实现 solution(budget: int, candidates: list[tuple[int, float]]) -> float。每个候选是长度 2 的序列 (cost, expected_return),第一个元素是整数成本,第二个是浮点期望回报。candidates[i] = [cost_i, expected_return_i],其中 cost_i 是买入名字 i 的一股所需整数美元,expected_return_i 是持有该股的绝对美元期望回报。组合经理可自由持有现金(现金回报为零),故返回值非负。candidates 为空或 budget 为零时均返回零值,结果类型为 Python float。
举例,solution(10, [[3, 4.0], [4, 5.0], [5, 6.0]]) 返回 11.0:在该预算下最优子集是成本为四与成本为五的两只(合计九元),回报 5.0 + 6.0 = 11.0;成本为三加成本为四仅得 9.0,而三只全买将超出预算。再如 solution(5, [[2, -1.0], [3, 4.0]]) 返回 4.0——成本为二的候选预期回报为负,组合经理在该名字上选择持有现金,只买入成本为三的候选。
实践背景
整股集中度约束在真实资金管理中无处不在:小盘 / 微盘组合中一手 100 美元的整股就可能突破单名 5% 的上限;期权 overlay 桌台买保护性 put 时合约张数必须为整数;UCITS 与 40-Act 基金受单一发行人持仓比例限制;家族办公室出于合规原因要求"每只名字至多 1 股"。这些场景下,连续型的均值-方差工具让位给整数规划,而这道题的一维 0/1 背包递推 dp[w] = max(dp[w], dp[w - cost] + ret) 反向扫描——正是小 N 情形下的标准实现。当 N 增大或叠加额外约束(行业上限、贝塔中性、换手率预算)时,生产环境会切换到分支定界或商用 MIP,但"一只名字一股"这一离散结构本身——也是把问题变难的根源——正是该 DP 所捕获的。
约束条件
- 0 ≤ `budget` ≤ 5000
- 0 ≤ N ≤ 200,其中 `N = len(candidates)`
- 每个候选是一个长度为 2 的列表 `[cost, expected_return]`
- 1 ≤ `cost` ≤ 5000(整数;一股整股,不允许碎股)
- -100.0 ≤ `expected_return` ≤ 100.0(浮点数;持有 1 股到下个截面的绝对美元 P&L)
- 每只名字至多 1 股——单名集中度上限强制 0/1 语义
- `candidates` 为空 → 返回 `0.0`;`budget == 0` → 返回 `0.0`
- 若没有任何子集能放进预算,返回 `0.0`(全部持有现金)
- 浮点比较容差:`rel_tol = 1e-9`,`abs_tol = 1e-12`
样例
Case 1 · three names: take cheap pair
输入: [10,[[3,4],[4,5],[5,6]]]
期望: 11
总预算 10,挑选成本为 3 和 4 的两个候选,合计 7 元,期望回报 4.0+5.0=9.0;若改选 4+5=9 元的两个,期望回报为 5.0+6.0=11.0,后者更优,故返回 11.0。
Case 2 · budget fits one name exactly
输入: [7,[[7,2.5],[3,1],[4,1.4]]]
期望: 2.5
预算恰好 7 元;买成本为 7 的候选回报 2.5,买成本为 3 与 4 的两只回报 1.0+1.4=2.4。比较后选前者,返回 2.5。
Case 3 · negative-return share is skipped
输入: [5,[[2,-1],[3,4]]]
期望: 4
成本为 2 的候选预期回报为负,持有现金优于持有它;只买成本 3 的候选,返回 4.0。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · three names: take cheap pair
输入: [10,[[3,4],[4,5],[5,6]]]
期望: 11
总预算 10,挑选成本为 3 和 4 的两个候选,合计 7 元,期望回报 4.0+5.0=9.0;若改选 4+5=9 元的两个,期望回报为 5.0+6.0=11.0,后者更优,故返回 11.0。
Case 2 · budget fits one name exactly
输入: [7,[[7,2.5],[3,1],[4,1.4]]]
期望: 2.5
预算恰好 7 元;买成本为 7 的候选回报 2.5,买成本为 3 与 4 的两只回报 1.0+1.4=2.4。比较后选前者,返回 2.5。
Case 3 · negative-return share is skipped
输入: [5,[[2,-1],[3,4]]]
期望: 4
成本为 2 的候选预期回报为负,持有现金优于持有它;只买成本 3 的候选,返回 4.0。