需求预测与计划
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read443 words

需求预测与计划

预测不准是供应链一切问题的根源——但我们能让它不那么不准。

需求计划架构

graph TD DATA[历史数据] --> STAT[统计模型] MARKET[市场信号] --> JUDGE[专家判断] STAT --> FORECAST[需求预测] JUDGE --> FORECAST FORECAST --> SOP[S&OP 产销协同] SOP --> SUPPLY[供应计划] SOP --> PRODUCTION[生产计划] SOP --> INVENTORY[库存计划] style FORECAST fill:#e3f2fd,stroke:#1565c0,stroke-width:2px style SOP fill:#c8e6c9,stroke:#388e3c,stroke-width:2px

预测方法

"""
需求预测模型
"""
from dataclasses import dataclass
@dataclass
class ForecastResult:
method: str
forecast: list[float]
mae: float  # 平均绝对误差
class DemandForecaster:
"""需求预测器"""
@staticmethod
def moving_average(
data: list[float], window: int = 3
) -> ForecastResult:
"""移动平均法"""
forecasts = []
errors = []
for i in range(window, len(data)):
avg = sum(data[i - window : i]) / window
forecasts.append(round(avg))
errors.append(abs(data[i] - avg))
# 下期预测
next_forecast = sum(data[-window:]) / window
forecasts.append(round(next_forecast))
mae = sum(errors) / len(errors) if errors else 0
return ForecastResult(
method=f"移动平均 (窗口={window})",
forecast=forecasts,
mae=round(mae, 1),
)
@staticmethod
def exponential_smoothing(
data: list[float], alpha: float = 0.3
) -> ForecastResult:
"""指数平滑法"""
forecasts = [data[0]]
errors = []
for i in range(1, len(data)):
f = alpha * data[i - 1] + (1 - alpha) * forecasts[-1]
forecasts.append(round(f))
errors.append(abs(data[i] - f))
# 下期预测
next_f = alpha * data[-1] + (1 - alpha) * forecasts[-1]
forecasts.append(round(next_f))
mae = sum(errors) / len(errors) if errors else 0
return ForecastResult(
method=f"指数平滑 (α={alpha})",
forecast=forecasts,
mae=round(mae, 1),
)
@staticmethod
def seasonal_naive(
data: list[float], season_length: int = 12
) -> ForecastResult:
"""季节朴素法"""
forecasts = data[:season_length]
errors = []
for i in range(season_length, len(data)):
f = data[i - season_length]
forecasts.append(round(f))
errors.append(abs(data[i] - f))
# 下期
forecasts.append(data[-season_length])
mae = sum(errors) / len(errors) if errors else 0
return ForecastResult(
method="季节朴素法",
forecast=forecasts,
mae=round(mae, 1),
)
# 演示 — 12个月销量
monthly_sales = [
1200, 1100, 1350, 1500, 1400, 1600,
1450, 1300, 1550, 1700, 1800, 2100,
]
forecaster = DemandForecaster()
print("=== 需求预测对比 ===")
methods = [
forecaster.moving_average(monthly_sales, 3),
forecaster.exponential_smoothing(monthly_sales, 0.3),
forecaster.seasonal_naive(monthly_sales, 12),
]
for result in methods:
next_month = result.forecast[-1]
print(f"\n{result.method}:")
print(f"  下月预测: {next_month}")
print(f"  MAE: {result.mae}")

牛鞭效应

需求放大从消费者到供应商逐级扩大:

"""
牛鞭效应模拟
"""
def bullwhip_simulation(
actual_demand: int,
amplification: float = 1.5,
levels: int = 4,
) -> dict:
"""模拟牛鞭效应"""
names = ["消费者", "零售商", "批发商", "制造商"]
result = {}
demand = actual_demand
for i in range(min(levels, len(names))):
result[names[i]] = {
"感知需求": round(demand),
"放大倍数": f"{demand / actual_demand:.1f}x",
}
demand *= amplification
return result
print("=== 牛鞭效应 (实际需求=100) ===")
for level, info in bullwhip_simulation(100).items():
print(f"  {level}: 感知 {info['感知需求']} ({info['放大倍数']})")
COUNTERMEASURES = {
"信息共享": "共享 POS 数据、库存数据",
"VMI 供应商管理库存": "供应商直接监控零售库存",
"CPFR 协同计划": "联合预测、联合补货",
"缩短前置期": "减少需求信号延迟",
"减少批量": "小批量高频补货",
"稳定价格": "避免促销导致的需求波动",
}
print("\n=== 缓解策略 ===")
for strategy, detail in COUNTERMEASURES.items():
print(f"  {strategy}: {detail}")

S&OP 产销协同

步骤 参与方 输出
1. 数据收集 市场/销售 销售预测
2. 需求评审 销售/市场 共识需求计划
3. 供应评审 供应链/生产 供应能力评估
4. 差距分析 全部 供需平衡方案
5. 管理层决策 高管 最终执行计划

预测准确度评估

指标 公式 用途
MAE 平均绝对误差 通用精度
MAPE 平均绝对百分比误差 跨品类对比
WMAPE 加权 MAPE 高值品更重要
Bias 预测偏差方向 检测系统性偏高/偏低

行动清单

下一节02-销售与运营计划S&OP — S&OP 月度流程与供需平衡实战。