案例 076 稳收还是搏一把
案例 076 稳收还是搏一把
摘要:保守方案 A 日均 320 ± 40 元,激进方案 B 多接远单、日均 355 ± 110 元;5 个情景的概率为 0.1/0.2/0.4/0.2/0.1。期望口径下 B 每天多 35.0 元,尾部口径下 B 的最差 10% 只有 164.5 元、A 有 250.7 元。把选择写成 0-1 变量 \(z\)、用 Rockafellar-Uryasev 形式把 CVaR 线性化成 \(\eta\) 与 \(w_{s}\) 的约束后,整个问题是一个 7 变量、11 条约束的 MILP。以 1.2 的 λ 求解,最优是方案 A,目标值 620.9 元对 552.4 元;λ 扫描给出临界 λ*=0.406——λ 低于这个数才该搏一把。风险厌恶只要超过 0.406,多出来的 35.0 元期望收益就买不回那 86.2 元的尾部差距。
关键词:均值-CVaR;方案选择;Rockafellar 线性化;临界 λ;风险厌恶;外卖日收益
1 问题提出
1.1 问题是什么
同一个骑手、同一天,两种跑法:A 老老实实跑近单、日收益 320 ± 40 元;B 多接远单、把单量堆上去,日均 355 ± 110 元。B 的波动是 A 的 2.8 倍。5 个情景(0.1/0.2/0.4/0.2/0.1)把这种差别摊开:好日子里 B 能跑到 546 元,坏日子里只剩 164 元;A 则在 251 到 389 元之间小幅摆动。
表 1 两方案在 5 个情景下的日净收益与差额(金额单位:元)
| 情景 | 概率 | A 收益 | B 收益 | B−A | 概率加权差额 |
|---|---|---|---|---|---|
| S1 极差 | 0.1 | 250.7 | 164.5 | -86.2 | -8.6 |
| S2 偏差 | 0.2 | 280.0 | 245.0 | -35.0 | -7.0 |
| S3 平常 | 0.4 | 320.0 | 355.0 | +35.0 | +14.0 |
| S4 偏好 | 0.2 | 360.0 | 465.0 | +105.0 | +21.0 |
| S5 极好 | 0.1 | 389.3 | 545.5 | +156.2 | +15.6 |
表 1 里最该盯住的不是均值差 35.0 元,而是最差情景:A 只掉到 251 元,B 掉到 164 元,两者差 86 元——比多赚的 35.0 元还大。平均下来 B 赢,最坏那天 B 输,这就是"稳收还是搏一把"的全部张力。
1.2 为什么要优化
第一,两种跑法的差别不在一个量纲上:多赚 35.0 元是确定的期望,多担的风险是尾部的。不把尾部折成一个数,争论只能停在"我觉得"。
第二,λ 是唯一能把"我觉得"翻译成决策的旋钮。λ=0 时谁都不会跟钱过不去;λ=∞ 时谁都不肯冒险。中间必然有一个翻转点,这个点算出来了,讨论才有落点。
第三,临界 λ 还能反着用:它告诉骑手"你现在的风险厌恶到什么程度就该换跑法",也告诉平台"想让骑手多接远单,得把尾部兜住多少"。
1.3 Gurobi 如何求解
决策只有 \(z\in\{0,1\}\)、一个自由的 \(\eta\)(VaR)、5 个非负的 \(w_{s}\)(尾部亏空),共 7 个变量、11 条线性约束,CVaR 是凸的,线性化之后是纯 MILP,没有非线性、没有二次项。分支定界只需判 \(z\) 的 0/1,根节点一次松弛即可定案,单次求解在毫秒级。
真正的工作量在参数扫描:λ 扫 7 点、β 扫 6 点、λ×波动 网格 20 点,另有 4000×20 天的蒙特卡洛做分布校核。全部墙钟 2 s,远低于 60 s 预算。
2 数学模型
2.1 符号说明
\(\pi_{s}\) 为情景概率,\(R^{A}_{s}\)、\(R^{B}_{s}\) 为两方案在情景 \(s\) 的日净收益,\(\ell_{s}\) 为损失(取负收益),\(z\) 为方案选择 0-1 变量(1 选 B),\(\eta\) 为 VaR、\(w_{s}\) 为尾部亏空,\(\beta\) 为置信水平,\(\lambda\) 为风险厌恶系数,\(M\) 为大 M。
2.2 目标函数
式 (1)(2) 是本案例的全部经济学:收益是 \(z\) 的线性函数,因为"二选一"落在两个已知常数之间。这一步很关键——方案选择不是黑箱,它就是一个加权,所以目标对 \(z\) 的系数只有两个取值,问题退化成"哪一边的目标值大"。
2.3 约束条件
式 (3)(4) 是 Rockafellar-Uryasev 形式:\(\eta\) 是最优 VaR,\(w_{s}=(\ell_{s}-\eta)^{+}\) 是情景 \(s\) 超出 VaR 的那一截。两个不等号缺一不可:漏掉 \(w_{s}\ge 0\),\(w_{s}\) 可以取负,式 (3) 求到的就不再是尾部均值而是它的下界,\(\lambda\) 越大模型越敢搏;漏掉 \(w_{s}\ge\ell_{s}-\eta\),\(w_{s}\) 全取 0,CVaR 退化成 \(\eta\),风险项被悄悄换成 VaR。
式 (5) 是题源结构:对 A、B 各写一组,用 \(M z\) 与 \(M(1-z)\) 互相屏蔽(题源写成 \(w_{s}\ge\eta-R_{s}\),那是配 \(\max\ \eta-\cdots\) 的收益口径;本案例取损失口径 \(\ell=-R\),符号随之翻转,两者等价)。式 (6) 是紧写法:既然 \(R_{s}(z)\) 本身就是线性的,屏蔽根本不需要,一条约束即可。两种写法在本案例给出完全相同的最优解(目标差小于 \(10^{-6}\)),但 (6) 的松弛更紧、不用挑 \(M\)——这在大规模问题里是实打实的差别。
式 (7) 是临界 λ 的闭式解,两方案目标相等时解出;式 (8) 说明 \(\eta\) 与 CVaR 的关系:\(\eta\) 只是一个分位点,CVaR 是分位点之外那一截的平均,恒有 \(\mathrm{CVaR}\le\eta\),两者在尾部只含一个原子时数值重合,这也是最容易被混用的地方。
2.4 规模与性质
7 个变量、11 条约束、1 个 0-1 变量。目标对 \(z\) 的系数固定为两常数,所以 \(z\) 的线性松弛必然取端点,分支定界的根节点就等于整数最优——这是"两方案选择"这类问题的共性:看起来是组合,其实是比较。
CVaR 的凸性是它能进线性模型的根本原因;换成 VaR 就不行,VaR 关于 \(z\) 不凸,同一个模型会变成非凸的,Gurobi 只能靠空间分支硬搜。
3 Gurobi 求解实现
3.1 建模要点
核心六行对应式 (2)(3)(4)(5):
z = m.addVar(vtype=GRB.BINARY); eta = m.addVar(lb=-1e3, ub=1e3)
w = m.addVars(NS, lb=0.0)
eexp = quicksum(PI[s] * (RA[s] + z * (RB[s] - RA[s])) for s in range(NS))
cv = eta + quicksum(PI[s] * w[s] for s in range(NS)) / (1 - beta)
for s in range(NS):
m.addConstr(w[s] >= -RA[s] - eta - M * z)
m.addConstr(w[s] >= -RB[s] - eta - M * (1 - z))
m.setObjective(eexp - lam * cv, GRB.MAXIMIZE)
第一条实现细节:\(\eta\) 的下界不能写 0。本题损失取 \(\ell=-R\),本身是负数,\(\eta\) 的最优值落在 251 元附近;若照题源把 \(\eta\ge 0\) 硬写上,\(w_{s}\ge\eta-\ell_{s}\) 的右端全为负,加上 \(w_{s}\ge 0\) 就直接把 \(w_{s}\) 压成 0,CVaR 算出来是 0.0,风险项整个失效,模型不管 λ 多大都选 B。这就是"约束写漏一个下界,结论翻个面"的实例。
第二条:\(M\) 取 1000 而不是 \(10^{6}\)。\(M\) 的量级只要盖住 \(|R^{A}-R^{B}|\) 的最大值 (86.2 元的量级) 就够,取太大会让松弛变松、数值变差。
3.2 求解结果
表 2 三处 λ 下的风险调整目标值与最优方案(金额单位:元)
| λ | A 目标值 | B 目标值 | 最优方案 | 含义 |
|---|---|---|---|---|
| 0.0 | 320.0 | 355.0 | B | 只算平均值 |
| 1.2 | 620.9 | 552.4 | A | 本案设定 |
| 0.406 | 421.7 | 421.7 | 两案等价 | 临界点 |
λ=0 时纯期望,B 以 35.0 元胜出;λ 抬到 1.2,A 反超 68.5 元;两者相等处就是 λ*=0.406。模型解出的 CVaR 与解析尾部均值一致(\(|\Delta|<10^{-6}\)),\(\eta\) 解出 -250.7 元,恰好等于所选方案最差情景收益的相反数——在 5 个情景、β=0.9 的设定下,尾部只有一个原子,\(\eta\) 与 CVaR 数值重合,这正好说明它们不是一回事:重合是巧合,不等才是常态(图 7 把 β 调到 0.8 就分开了 40.3 元)。
4 结果分析

图 1 两方案在 5 个情景下的日净收益与情景概率
4.1 结构:情景与概率 图 1 把两种跑法并排摆开,灰色柱是情景概率。中间三个情景(概率合计 0.8)两方案差距不大,赌注全压在两端:S1 上 B 比 A 少 86 元,S5 上 B 比 A 多 156 元。概率 0.1 的两端决定了尾部,概率 0.4 的中间决定了均值——这就是"稳收"和"搏一把"各自的地盘。

图 2 期望—尾部均值平面上的 A/B 与等效用线(气泡为波动幅度)
4.2 期望—尾部平面 图 2 横轴是尾部均值(CVaR 90%)、纵轴是期望,气泡大小是波动。B 在右上方(期望高)、左下方(尾部差),A 反过来。λ=1.2 的等效用线斜率是 \(-1.2\),A 那条线整体压在 B 之上——几何上就一眼看出该选 A。紫色方块是 B 的波动从 60.0 加到 150.0 元的轨迹:波动每加一档,点就往左挪一截,等效用线很快被甩到下面。

图 3 λ=0、λ=1.2 与临界 λ 三处的目标值对比
4.3 三处 λ 的方案对比 图 3 是全案例的主图。λ=0:A 320.0 元、B 355.0 元,选 B;λ=1.2:A 620.9 元、B 552.4 元,选 A;λ=0.406:两者同为 421.7 元左右,箭头标着"两案等价"。同一组数据,只换一个 λ,结论从"搏一把"翻成"稳收"——这正是骑手群里吵不出结果的原因:大家说的不是同一个 λ。

图 4 两方案日收益的累计分布与 10% 尾部线
4.4 累计分布 图 4 是两条阶梯 CDF。10% 尾部线以下,A 的曲线在 250.7 元处就被截断,B 拖到 164.5 元,中间空出 86.2 元。β=0.9 的 CVaR 就是这条线左侧那一小块的平均,所以两条曲线的左端距离,直接就是目标函数里的风险项差价。CDF 交叉发生在 280 元附近,交叉点以右 B 全面占优,交叉点以左 B 全面落后。

图 5 λ 扫描:两方案目标值与目标差,虚线为 B 的波动变化
4.5 主灵敏度:λ 与 B 的波动 图 5 左轴两条直线,A 的斜率 250.7 元/元、B 的斜率 164.5 元/元(斜率就是各自的尾部均值),在 λ*=0.406 处交叉。右轴柱状是目标差 A−B,随 λ 线性上升、过零即翻转。虚线族是 B 的波动:σ 从 110 降到 80(虚线),交叉点推到 λ≈1.02;升到 150(点线),交叉点前移到 λ≈0.23。波动越大,翻转来得越早——越是"搏一把"的跑法,越经不起一点风险厌恶。

图 6 λ × 波动 网格上的最优方案与临界 λ 曲线
4.6 二维:λ × 波动 图 6 的 20 个格子里,浅色是选 A、深色是选 B,黑线是解析的临界 λ 曲线 \(\lambda^{*}(\sigma^{B})=35/(1.732\sigma^{B}-104.3)\),单调下降。星标是本案(λ=1.2,σ=110),落在深色的 A 区深处,离边界还有一段距离——说明本案的结论不是"擦边过",而是明确地选 A。σ 降到 60 元以下,B 的尾部反超 A,曲线失效,任何 λ 都选 B。

图 7 置信水平 β 扫描:VaR(η) 与 CVaR 的分离及临界 λ
4.7 第三维:置信水平 β 图 7 是本文最该看的一张。左轴蓝红实线是两方案的 CVaR,蓝色虚线是 A 的 VaR(\(\eta\))、红色虚线是 B 的 VaR。β=0.9 处两条虚线正好压在实线上(尾部只有一个情景),β 降到 0.8,B 的 \(\eta\) 比 CVaR 高 40.3 元——分位点永远不低于尾部均值,把 \(\eta\) 当成 CVaR 就会系统性高估风险。右轴是临界 λ(β):β 从 0.7 升到 0.95,λ* 从 0.672 降到 0.406,因为 β 越高、尾部越尖,A 在尾部的优势越突出。对风险越敏感,越该稳收。

图 8 期望—尾部均值前沿与风险下限以下的不可行区
4.8 前沿与不可行区 图 8 的灰区是 CVaR 低于 200 元的部分。如果骑手给自己划一条"最坏 10% 平均不低于 200 元"的底线,B(164.5 元)直接掉进灰区,再大的 λ 也救不回来——那是可行性问题,不是偏好问题。虚线是 A/B 的混合策略,全程是一条直线:CVaR 关于混合比例是线性的(正齐次 + 凸),所以混合永远不产生新的非支配点,最优解必然落在端点上。这就是"要么全稳、要么全搏"的数学解释。

图 9 20 个工作日累计收益的分布(4000 次模拟)
4.9 分布校核 图 9 用 4000 次、每次 20 个工作日的抽样,把单日的情景拉成月度分布。均值 B 是 7105 元、A 是 6402 元;95% 分位 7892 对 6688 元,跨度 1583.2 元对 575.7 元。5% 分位 B 反而高些(6308 对 6112 元),因为它的均值本来就高;但相对自身均值,B 最深下探 797 元、A 只下探 290 元。单日看只差 86.2 元的尾部,摊到 20 天就是 507 元的落差——这正是 CVaR 想压住的东西在时间上的放大。

图 10 B 相对 A 的期望差额逐情景分解
4.10 差额的边际贡献 图 10 把 B 相对 A 的 35.0 元差额拆到 5 个情景上。S3、S4、S5 三个情景合计贡献 +50.6 元,S1、S2 两个情景合计 −15.6 元,净剩 35.0 元。尾部那两个情景贡献了负的大头(-8.6 与 -7.0),而它们正是尾部损失的来源:B 的期望优势,本质是"用两个坏情景的深度亏损,换三个好情景的额外收入"。买不买这个交换,取决于 λ。
5 结论
-
期望口径选 B,风险口径选 A。 λ=0 时 B 多 35.0 元;λ=1.2 时 A 反超 68.5 元。同一组数据、同一套约束,只换一个 λ,答案就翻面。
-
临界 λ*=0.406。 这是本案例的主结论:风险厌恶系数低于 0.406 时搏一把更划算,高于它就稳收。B 的 35.0 元期望溢价,只值 0.406 单位的尾部风险。
-
CVaR 的线性化是"凸性换规模"。 \(\eta\) 与 5 个 \(w_{s}\) 把最坏 10% 的平均写成了线性表达式,7 个变量、11 条约束、毫秒求解;换成 VaR 则非凸,模型性质完全不同。
-
\(\eta\ne\mathrm{CVaR}\)。 \(\eta\) 是分位点,CVaR 是尾部均值,恒有 \(\mathrm{CVaR}\le\eta\)。本案 β=0.9 时两者数值重合(尾部只有一个情景),β=0.8 时差 40.3 元;把 \(\eta\) 当下界写进约束、或把 \(w_{s}\ge 0\) 写漏,模型会静默失效——前者让 CVaR 恒为 0.0,后者让风险项归零。
-
波动是翻转的加速器。 B 的波动从 80 元升到 150.0 元,临界 λ 从 1.02 掉到 0.23;波动越大,越早该稳收。而一旦给自己划了风险下限(CVaR 不低于 200 元),B 直接不可行——可行性问题不能靠调 λ 解决。
参考文献
[1] Gurobi Optimization LLC. Gurobi Optimizer Reference Manual[Z]. 2024.
[2] Kellerer H, Pferschy U, Pisinger D. Knapsack Problems[M]. Berlin: Springer, 2004.
[3] Martello S, Toth P. Knapsack Problems: Algorithms and Computer Implementations[M]. Chichester: John Wiley & Sons, 1990.
[4] 司守奎, 孙玺菁. 数学建模算法与应用[M]. 3 版. 北京: 国防工业出版社, 2021.

浙公网安备 33010602011771号