用 Codex 做补货预测,先把断货那几天从均值里剔掉
断货和压货的代价不对称,但很多店的补货判断卡在更早的地方:日均销量算错了。断货那几天销量是零,直接算进均值会把日均拉低,于是补得更少,于是更容易断货,而报表上看一切正常。正确做法是先剔除断货日和促销日再算基准销速,用中位数而不是平均数,再叠加波动系数。新品没有历史、季节品有周期、大促前后销量结构变,这三种情况一律交给人判断。
先讲结论:多数人算错的不是公式,是日均
补货这件事,公式本身不复杂:算出日均销量,乘以备货周期,加上安全库存,减去现有和在途,就是该补的量。
但很多店的补货判断从第一步就偏了——日均销量算错。
最典型的一个错误:把断货那几天算进了均值。
某个 SKU 上个月断货 8 天,这 8 天销量是零。如果直接拿 30 天总销量除以 30,日均会被拉低约四分之一。按这个偏低的日均去补货,补的量更少,下次更容易断货,断货天数更多,日均被拉得更低。
这是一个能自我强化的死循环,而且从报表上看完全正常——数字没错,逻辑错了。
所以这篇的重点不是公式,是数据清洗。
需要哪些数据
- 每日销量,至少 90 天,越长越好
- 每日库存快照,用来识别哪天断货了
- 在途数量和预计到货时间
- 各环节的时间:生产周期、头程运输、平台入库上架
- 成本,用来算压货金额
- 促销和活动的日期记录
最后一项经常没有。如果没有,退而求其次:让它自己识别销量异常高的日子,标出来问你那天是不是有活动。
这个活是纯本地的,只读就够:
sandbox_mode = "read-only"
approval_policy = "on-request"
报告让它输出到标准输出,由外层脚本写文件。这样连写权限都不需要。
清洗规则:哪些天要剔掉
算基准销速之前,先把这几类日子排除:
- 断货日:库存为零或低到无法正常出单的日子。这些天的零销量不代表没需求
- 限制出单日:因为账号问题、类目审核、物流异常导致的不能正常销售
- 大促日:黑五、会员日这类日子的销量不能代表日常水位
- 大促后的低谷:大促后通常有几天销量明显低于平时,也要排除
剔完之后剩下的才是「正常日」,用正常日算日均。
这里有一个判断要留给人:如果 90 天里正常日不足 30 天,说明这个 SKU 的销售根本不稳定,任何预测都不可靠。这种情况让它直接输出「数据不足以预测」,而不是硬算一个数出来。
用中位数,不用平均数
清洗不可能做得完美,总会有漏网的异常日。
所以基准日均建议用中位数而不是平均数。中位数对残留的异常值更不敏感,相当于在清洗之外多一层保险。
一个直观的例子:某 SKU 十天的销量是 8、9、10、9、11、10、9、10、120、9。那个 120 是漏掉的活动日。平均数是 20.5,中位数是 9.5。哪个更接近真实水位,一目了然。
波动比均值更重要
算出日均之后,还要算波动。
两个 SKU 都是日均 10 单,一个每天稳定 9 到 11 单,另一个在 2 到 30 单之间跳。它们需要的安全库存完全不同。
所以安全库存不能拍脑袋定一个「多备两周」,应该跟着波动走:波动小的少备,波动大的多备。
同时要看断货的代价。有些 SKU 断货几天影响有限,有些 SKU 断货会掉排名、恢复要花几周——后者的安全库存应该显著更高。
这一层是业务判断,需要你自己给每个 SKU 打个标签,写进数据里让它读。
三条时间线要分开算
备货周期不是一个数,是好几段加起来:
- 下单到工厂出货
- 头程运输
- 到仓到上架可售
这三段的波动性差别很大。生产周期相对可控,海运时效波动最大,入库上架在旺季会明显变慢。
分开记录的好处是出问题时能定位:这次断货是工厂拖了,还是港口堵了,还是仓库入库慢了。合成一个数就查不出来了。
规则文件怎么写
## 数据
读取 data/inventory/ 下:
sales-daily.csv、stock-daily.csv、in-transit.csv、leadtime.csv、cost.csv、events.csv(可选)
任何一份缺失,跳过依赖它的检查,并在报告里写明缺哪份,不要用估算值代替。
## 清洗规则
算基准销速前,从样本中剔除:
- 库存为零或低于可售阈值的日子
- events.csv 中标记的促销日,以及促销结束后的 3 天
- 销量为当期中位数 3 倍以上的日子,标出来在报告里说明原因
剔除后剩余的正常日不足 30 天时,该 SKU 输出「数据不足以预测」,不给补货量。
## 计算
- 基准日均 = 正常日销量的中位数
- 波动系数 = 正常日销量的标准差 ÷ 基准日均
- 总备货周期 = 生产 + 头程 + 上架,三段分别列出
- 安全库存 = 基准日均 × 总备货周期 × 波动系数
- 补货点 = 基准日均 × 总备货周期 + 安全库存
- 建议补货量 = 补货点 − 现有库存 − 在途
## 输出
1. 紧急清单:预计断货日早于最快到货日的 SKU,按缺口金额排序
2. 常规补货清单:已低于补货点的,含建议量和依据
3. 数据不足清单:无法预测的,说明缺什么
4. 滞销清单:超过 60 天零动销的 SKU 和占压金额
5. 每个 SKU 的计算过程要能展开:基准日均、波动系数、三段周期各是多少
## 禁止动作
- 不下采购单,不调用任何接口
- 不为数据不足的 SKU 编造预测值
- 新品(销售不足 30 天)、明显季节性商品、大促前后 14 天内,
一律标注「需人工判断」,不给自动建议
第五条「计算过程要能展开」值得强调。补货是要花钱的决定,你需要能看懂它为什么给出这个数。一个只有结论没有过程的报告,你要么盲信,要么不敢用。
三种情况一定要人来判断
新品
没有历史数据,任何预测都是猜。新品的补货依据是别的东西:同类目相似产品的表现、广告投放计划、首批的实际动销速度。这些信息不在数据表里。
新品的正确做法是小批量试,用真实数据把销速跑出来,再交给自动化。
季节性商品
有明显季节周期的商品,用最近 90 天推未来完全不成立。夏天的数据推冬天的需求,方向可能是反的。
这类商品需要看去年同期,而且要人来判断今年和去年有什么不同。
大促前后
大促前要提前备货,大促后会有一段低谷,这两段的销量结构和平时不是一回事。
而且大促备货量取决于你打算投多少广告、报没报上活动——这些是计划,不是历史数据能推出来的。
报告出来之后
报告的作用是把决策依据摆清楚,最后拍板还是人。拍板时至少再看三件事:
- 资金:这批货压多少钱,账上撑不撑得住
- 仓储:仓库容量和仓储费,压货本身有持有成本
- 产品生命周期:这个 SKU 还能卖多久,快要淘汰的别按常规周期补
第三条最容易漏。一个准备退市的 SKU,按公式该补 500 个,但实际上一个都不该补。这个信息只在人的脑子里。
跑成定时任务
补货报告适合每周固定跑一次,用非交互模式:
codex exec \
--sandbox read-only \
--ask-for-approval never \
"按 AGENTS.md 的规则生成本周补货报告" \
> "reports/restock-$(date +%F).md"
有一条要写进规则:数据文件缺失时明确失败,不要用旧数据代替。
补货这个场景里,这一条比别处更要紧——拿两周前的库存快照算出来的补货建议,会让你补错量,而报告看起来完全正常。
下一步
场景篇到这里结束。最后两篇回到判断层面:成本怎么算才不会算错、本地模型该怎么分流,以及和同类工具怎么选。




