按夏普比率排序策略(波动率作为次序)
Rank Strategies by Sharpe with Vol Tiebreak
开始编码策略评估会上,研究主管把当季所有候选策略的日收益序列拍在桌上,要一张风险调整后的排行榜:每条策略要算出夏普比率(mean / std),按从高到低排序。但单看夏普还不够——两条策略夏普恰好打平时,直觉上应该把波动率更低的那条排在前面:相同的风险调整收益,谁吃的风险更少谁就更靠谱。这是研究流程里很常见的"主指标 + 次序指标"组合,做法上是一次多关键字排序。
请实现 solution(strategies: list[dict]) -> list[dict]。每条 strategies[i] 是一个 dict,至少可能包含 name(策略名)和 returns(日收益序列),也可能带着别的元数据,忽略即可。请按下面的口径处理:
- 清洗。先
name.strip();若name缺失、为None、剥空白后为空字符串,整条策略丢弃。若returns缺失、为None、或长度 < 2,整条策略丢弃(样本标准差需要至少两个观测才有意义)。 - 统计。
mean = sum(returns) / n,vol = stdev(returns)(样本标准差,分母是n - 1,即 Pythonstatistics.stdev的口径)。sharpe = mean / vol。若vol == 0.0(收益完全恒定,比如全是 0.0 或全是 0.001),夏普未定义,整条策略丢弃。 - 打包。每条幸存策略输出
{"name": str, "sharpe": float, "vol": float},两个浮点字段都用round(x, 4)截到 4 位小数(这样不同实现的浮点尾差不会让compare: "exact"翻车)。 - 排序。先按
sharpe降序——夏普高的排前面;夏普相等再按vol升序——更低风险的同夏普策略更靠谱;仍然相等按name字典序升序——保证返回顺序对相同输入是确定的。
举例:solution([{"name": "Alpha", "returns": [0.01, 0.02, 0.03, 0.04]}, {"name": "Beta", "returns": [0.01, 0.01, 0.05, 0.05]}, {"name": "Gamma", "returns": [-0.01, 0.0, 0.01, 0.04]}]) 应返回 [{"name": "Alpha", "sharpe": 1.9365, "vol": 0.0129}, {"name": "Beta", "sharpe": 1.299, "vol": 0.0231}, {"name": "Gamma", "sharpe": 0.4629, "vol": 0.0216}](数值经 round(_, 4) 后展示)。Alpha 收益每天稳步加 1bp 上去,方差小、夏普最高;Beta 在 1bp 与 5bp 之间剧烈跳,均值更高但方差也更大,夏普反而被拉下来;Gamma 收益分布在 0 附近,均值最低,夏普被压到最末位。
5000 条策略、每条 returns 长度可达数百的体量下,请用 O(N · L + N log N) 的方案:单遍扫每条策略算两个统计量、一次 sorted 完成多关键字排序,这样的复杂度对应日常的批量评估场景就足够了。
约束条件
- 0 ≤ len(strategies) ≤ 5000
- 每条策略是形如 `{"name": str, "returns": list[float], ...}` 的字典;其余字段忽略
- 对 `name` 调用 `.strip()` 后再使用;若 `name` 缺失、为 `None` 或剥空白后为空,整条策略丢弃
- 若 `returns` 缺失、为 `None` 或长度 < 2,整条策略丢弃(样本标准差需要 ≥ 2 个观测)
- 波动率定义为**样本标准差**(除以 `n-1`,即 `statistics.stdev` 的口径);夏普定义为 `mean / vol`
- 若某条策略的 `vol == 0.0`(即所有收益完全相同,方差为零),夏普未定义,整条策略丢弃
- 返回值是 list[dict],每个 dict 形如 `{"name": str, "sharpe": float, "vol": float}`,其中两个浮点字段都通过 `round(x, 4)` 精确到 4 位小数
- 排序:先按 `sharpe` 降序;相等再按 `vol` 升序;仍相等按 `name` 字典序升序
样例
Case 1 · example from statement (three strategies, distinct sharpe)
输入: [[{"name":"Alpha","returns":[0.01,0.02,0.03,0.04]},{"name":"Beta","returns":[0.01,0.01,0.05,0.05]},{"name":"Gamma","returns":[-0.01,0,0.01,0.04]}]]
期望: [{"name":"Alpha","sharpe":1.9365,"vol":0.0129},{"name":"Beta","sharpe":1.299,"vol":0.0231},{"name":"Gamma","sharpe":0.4629,"vol":0.0216}]
Alpha 收益每天稳步加 1bp,mean=0.025、vol=0.0129、sharpe=1.9365 排第一;Beta 在 1bp 与 5bp 之间剧烈跳,mean=0.03 看似更高但 vol=0.0231 拉胯,sharpe=1.299 落到第二;Gamma 收益分布在 0 附近,mean=0.01、vol=0.0216,sharpe=0.4629 垫底。
Case 2 · sharpe ties broken by lower vol
输入: [[{"name":"Loud","returns":[0.02,0.04,0.06,0.08]},{"name":"Quiet","returns":[0.01,0.02,0.03,0.04]},{"name":"Bright","returns":[0.03,0.06,0.09,0.12]}]]
期望: [{"name":"Quiet","sharpe":1.9365,"vol":0.0129},{"name":"Loud","sharpe":1.9365,"vol":0.0258},{"name":"Bright","sharpe":1.9365,"vol":0.0387}]
三条策略的收益序列分别是 1x / 2x / 3x 的等比缩放,mean 与 std 同时同倍数变化、Sharpe 完全相等(=1.9365)。规则要求同 sharpe 时按 vol 升序:Quiet 0.0129 < Loud 0.0258 < Bright 0.0387,最稳的策略排在前面。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · example from statement (three strategies, distinct sharpe)
输入: [[{"name":"Alpha","returns":[0.01,0.02,0.03,0.04]},{"name":"Beta","returns":[0.01,0.01,0.05,0.05]},{"name":"Gamma","returns":[-0.01,0,0.01,0.04]}]]
期望: [{"name":"Alpha","sharpe":1.9365,"vol":0.0129},{"name":"Beta","sharpe":1.299,"vol":0.0231},{"name":"Gamma","sharpe":0.4629,"vol":0.0216}]
Alpha 收益每天稳步加 1bp,mean=0.025、vol=0.0129、sharpe=1.9365 排第一;Beta 在 1bp 与 5bp 之间剧烈跳,mean=0.03 看似更高但 vol=0.0231 拉胯,sharpe=1.299 落到第二;Gamma 收益分布在 0 附近,mean=0.01、vol=0.0216,sharpe=0.4629 垫底。
Case 2 · sharpe ties broken by lower vol
输入: [[{"name":"Loud","returns":[0.02,0.04,0.06,0.08]},{"name":"Quiet","returns":[0.01,0.02,0.03,0.04]},{"name":"Bright","returns":[0.03,0.06,0.09,0.12]}]]
期望: [{"name":"Quiet","sharpe":1.9365,"vol":0.0129},{"name":"Loud","sharpe":1.9365,"vol":0.0258},{"name":"Bright","sharpe":1.9365,"vol":0.0387}]
三条策略的收益序列分别是 1x / 2x / 3x 的等比缩放,mean 与 std 同时同倍数变化、Sharpe 完全相等(=1.9365)。规则要求同 sharpe 时按 vol 升序:Quiet 0.0129 < Loud 0.0258 < Bright 0.0387,最稳的策略排在前面。