paper2skills Playbook

Constructing decision rules for multiproduct newsvendors

Skill-Multi-SKU-Procurement-Budget-Allocation · 04-供应链

causalexperimentforecastingoptimizationpricing供应链与补货定价与利润WF-A 智能补货WF-D 选品扫描WF-F 动态定价
年化 ROI$60,000-$100,000(4 个季度)
实现难度⭐⭐☆☆☆
业务视角
适用角色供应链负责人 · 采购负责人 · CEO / 运营 VP
适用平台Amazon FBA · 海外仓 · 多国仓位(美/欧/日)
什么情况下用库存周转率低,资金压在海外仓出不来;SKU 断货紧急空运,物流成本吃掉毛利;多仓库存分布不均
成功是什么样的库存周转天数从 90 天降到 60 天,断货率 <3%,海外仓综合成本降低 15-25%
业务痛点
库存周转天数太长资金压死了断货了只能空运救急成本爆了多市场库存分配不均

1. 解决的问题

场景 A:季度 $200K 预算在 8 个核心 SKU 间分配

2. 核心算法逻辑

核心思想:季度采购预算有限时,不能对每个 SKU 独立做 Newsvendor 决策——预算约束把所有 SKU 耦合成一个联合优化问题。Knapsack Ordering 算法提供了一个 O(n) 的近最优分配方案:按每个 SKU 的「边际成本效应」排序,依序分配资金直到预算耗尽,同时通过差异化缺货成本系数(cᵤᵢ)将毛利率/战略优先级编码进目标函数。

3. 业务应用场景

场景 A:季度 $200K 预算在 8 个核心 SKU 间分配

- 业务问题:Q4 备货预算 $200,000,8 个 SKU,各有不同毛利率和需求不确定性,如何分配才能最大化整体服务水平并保障高毛利 SKU 不断货? - 数据要求:每 SKU 的历史需求均值/标准差、采购单价、毛利率、BSR 重要性评级 - 预期产出: - 业务价值:相比「平均分配」或「按需求比例」,Knapsack Ordering 可将整体服务水平从 ~85% 提升至 ~92%,对应减少缺货损失约 $15,000-$25,000/季度

场景 B:新品上市预算挤占存量 SKU 资金的优先级决策

4. 输入数据要求

请查看原始代码模板获取输入规格。

5. 输出结果

请查看原始代码模板获取输出规格。

6. 业务价值 / ROI

  • ROI 预估
  • 相比平均分配策略,Knapsack Ordering 将加权服务水平从约 85% 提升至约 92%
  • 7pp 服务水平提升 × $200K 季度采购 × 缺货损失系数 ≈ 减少缺货损失约 $15,000-$25,000/季度
  • 年化:$60,000-$100,000(4 个季度)
  • Budget-Consistency 降级策略:预算削减时,直接截断低优先级 SKU,零额外计算成本
  • 实施难度:⭐⭐☆☆☆(2/5)— O(n) 排序算法,无需求解器

7. 代码模板

代码块数量:6 · 路径:未检测到

"""
Skill-Multi-SKU-Procurement-Budget-Allocation
基于 arXiv:2301.02662 (Boonstra et al. 2023, Knapsack Ordering) +
    EJOR Vol.315 2024 (Olivares-Nadal, 战略优先级加权)
母婴跨境 DTC 多 SKU 季度采购预算分配优化
"""

import numpy as np
from dataclasses import dataclass, field
from scipy import stats
from scipy.optimize import brentq


@dataclass
class SKUSpec:
    sku_id: str
    demand_mean: float
    demand_std: float
    unit_price: float
    gross_margin_rate: float
    stockout_bsr_penalty: float = 1.5
    strategic_priority: str = "medium"

    @property
    def holding_cost_per_unit(self) -> float:
        return self.unit_price * 0.20 / 4

    @property
    def stockout_cost_per_unit(self) -> float:
        return self.unit_price * self.gross_margin_rate * self.stockout_bsr_penalty

    @property
    def critical_ratio(self) -> float:
        cu, co = self.stockout_cost_per_unit, self.holding_cost_per_unit
        return cu / (cu + co)


@dataclass
class AllocationResult:
    sku_id: str
    order_qty: float
    budget_allocated: float
    service_level: float
    marginal_value: float
    rank: int
    truncated: bool = False


def newsvendor_qty(sku: SKUSpec, critical_ratio: float | None = None) -> float:
    cr = critical_ratio if critical_ratio is not None else sku.critical_ratio
    return max(0.0, stats.norm.ppf(cr, loc=sku.demand_mean, scale=sku.demand_std))


def lagrangian_allocation(skus: list[SKUSpec], budget: float) -> list[AllocationResult]:
    """
    Lagrangian 松弛:二分搜索 λ* 使预算约束恰好满足。
    适合需求分布已知(Normal)的场景。
    """
    def total_spend(lam: float) -> float:
        total = 0.0

8. 论文来源

  • 2301.02662