
如果把品牌比作一支乐队电商、实体店、私域就是三大乐手而备货比例就是给每个乐手分配多少演奏时间。咱们今天就用 Python 当指挥棒把这场库存交响乐的比例调校清楚。线上线下多渠道利润分配与备货平衡算法(Omni-Channel Inventory Allocation Profit Distribution Engine)定位教学级多渠道库存优化与利润归因工具语言Python 3.10适用场景时尚产业与品牌创新课程、全渠道供应链管理、零售利润优化一、实际应用场景描述在现代时尚零售体系中品牌普遍采用全渠道Omni-Channel策略同时运营- 电商平台天猫、京东、抖音小店触达广、转化快、价格敏感- 实体门店直营店、商场专柜体验好、客单价高、库存周转慢- 私域渠道微信社群、小程序、会员体系复购高、运营成本低、流量有限在制订季度商品企划时核心决策问题是有限的库存如 5000 件新品应该按什么比例分配到三个渠道如何在卖得动和赚得多之间找到最优解这不是简单的三七开能解决的需要量化模型支撑。二、引入痛点行业现实问题1. 拍脑袋定比例缺乏数据依据- 常见做法电商 50%、门店 35%、私域 15%——依据是什么- 不同品类、不同季节、不同城市等级的最优比例完全不同- 缺少一个可计算的优化框架2. 各渠道利润逻辑不统一渠道 成本结构 利润驱动因素电商 平台扣点高、物流成本 走量、转化率实体店 租金人力重、装修摊销 客单价、连带率私域 获客成本低、运营轻 复购率、信任转化用同一把尺子衡量三个渠道必然失真。3. 库存错配代价高昂- 电商缺货 → 错失流量窗口期平台活动就那几天- 门店积压 → 季末打折伤品牌- 私域没货 → 老客户流失三、核心逻辑讲解建模思路1. 核心假设教学简化- 总库存量固定约束条件- 各渠道有独立的单位经济模型售价、成本、费率不同- 目标函数最大化总净利润- 约束条件各渠道最低/最高备货量如门店不能低于展示量2. 关键变量定义变量 含义total_inventory 总可用库存件unit_cost 单件成本元price_ecom /price_store /price_private 各渠道售价platform_fee_rate 电商平台扣点比例store_opex_per_unit 门店单件运营分摊成本private_conversion_rate 私域转化率min_store_stock 门店最低陈列库存max_ecom_stock 电商最大可承载库存仓储/平台限制3. 利润公式渠道净利润 销量 × (售价 − 成本 − 渠道专属费用)电商净利润 销量 × (price_ecom − unit_cost − price_ecom × platform_fee_rate)门店净利润 销量 × (price_store − unit_cost − store_opex_per_unit)私域净利润 销量 × (price_private − unit_cost) 无平台扣点总净利润 Σ 各渠道净利润4. 优化思路遍历搜索法由于只有 3 个渠道可以用离散遍历寻找最优分配遍历电商库存: 0 → total_inventory遍历门店库存: 0 → (total_inventory − 电商库存)私域库存 剩余计算总利润记录最大值工程实践中可用线性规划SciPy或启发式算法此处为教学可读性采用遍历法。四、项目结构channel-allocation-engine/│├── README.md├── USAGE.md├── main.py├── modules/│ ├── channel.py # 渠道利润模型│ ├── optimizer.py # 库存分配优化引擎│ ├── constraints.py # 约束条件校验│ └── reporter.py # 结果输出与对比└── config/└── allocation.yaml五、核心代码实现Python1️⃣ 渠道利润模型channel.py# channel.py# 定义各渠道的独立利润计算模型from dataclasses import dataclassfrom typing import Optionaldataclassclass ChannelProfile:单个渠道的利润属性配置name: strunit_cost: float # 单件成本共享selling_price: float # 渠道售价variable_cost_per_unit: float # 渠道专属变动成本扣点/运费等fixed_cost_total: float 0.0 # 渠道固定成本总额可选max_capacity: Optional[int] None # 最大可承载库存min_stock: Optional[int] None # 最低保底库存def profit_per_unit(self, sold: int) - float:计算该渠道的单件毛利润if sold 0:return 0.0revenue sold * self.selling_pricevariable_costs sold * (self.unit_cost self.variable_cost_per_unit)return revenue - variable_costs - self.fixed_cost_totaldef unit_margin(self) - float:单件贡献毛利不含固定成本return self.selling_price - self.unit_cost - self.variable_cost_per_unitdef build_channel_profiles(unit_cost: float) - dict:工厂方法构建三个渠道的配置return {ecom: ChannelProfile(name电商平台,unit_costunit_cost,selling_price299.0,variable_cost_per_unit299.0 * 0.08, # 平台扣点 8%fixed_cost_total5000, # 平台年费/推广费分摊),store: ChannelProfile(name实体门店,unit_costunit_cost,selling_price459.0,variable_cost_per_unit65.0, # 租金人力水电分摊/件fixed_cost_total30000, # 门店固定开支min_stock200, # 最低陈列量),private: ChannelProfile(name私域渠道,unit_costunit_cost,selling_price349.0,variable_cost_per_unit15.0, # 小程序手续费包装fixed_cost_total2000, # 社群运营分摊),}2️⃣ 约束条件校验constraints.py# constraints.py# 校验库存分配是否满足业务约束from modules.channel import ChannelProfiledef validate_allocation(ecom_stock: int,store_stock: int,private_stock: int,profiles: dict,total_inventory: int) - tuple[bool, str]:校验一组分配方案是否合法返回(is_valid, error_message)# 1. 总量守恒if ecom_stock store_stock private_stock ! total_inventory:return False, 库存总量不匹配# 2. 非负if any(s 0 for s in [ecom_stock, store_stock, private_stock]):return False, 库存不能为负# 3. 门店最低陈列store profiles[store]if store.min_stock and store_stock store.min_stock:return False, f门店库存低于最低陈列量 {store.min_stock}# 4. 电商最大容量ecom profiles[ecom]if ecom.max_capacity and ecom_stock ecom.max_capacity:return False, f电商库存超过最大承载量 {ecom.max_capacity}return True, def apply_capacity_constraints(profiles: dict,total_inventory: int) - dict:根据渠道配置生成约束边界return {ecom_max: profiles[ecom].max_capacity or total_inventory,store_min: profiles[store].min_stock or 0,store_max: total_inventory,private_max: total_inventory,}3️⃣ 优化引擎optimizer.py# optimizer.py# 通过遍历搜索最优库存分配方案from modules.channel import ChannelProfilefrom modules.constraints import validate_allocationdef calculate_total_profit(ecom_stock: int,store_stock: int,private_stock: int,profiles: dict,sell_through_rates: dict) - float:计算给定分配方案下的总净利润sell_through_rates: 各渠道预计售罄率0~1total 0.0for channel_key, stock in [(ecom, ecom_stock),(store, store_stock),(private, private_stock),]:profile: ChannelProfile profiles[channel_key]expected_sales int(stock * sell_through_rates[channel_key])profit profile.profit_per_unit(expected_sales)total profitreturn round(total, 2)def find_optimal_allocation(total_inventory: int,profiles: dict,sell_through_rates: dict,step: int 50) - dict:遍历搜索最优库存分配方案step: 遍历步长件越小越精确越大越快返回{best_ecom: int,best_store: int,best_private: int,max_profit: float,all_results: list # 所有可行方案}best_profit float(-inf)best_alloc Noneall_results []# 遍历电商库存for ecom_s in range(0, total_inventory 1, step):# 遍历门店库存for store_s in range(0, total_inventory - ecom_s 1, step):private_s total_inventory - ecom_s - store_sis_valid, _ validate_allocation(ecom_s, store_s, private_s, profiles, total_inventory)if not is_valid:continueprofit calculate_total_profit(ecom_s, store_s, private_s, profiles, sell_through_rates)entry {ecom: ecom_s,store: store_s,private: private_s,profit: profit,}all_results.append(entry)if profit best_profit:best_profit profitbest_alloc entryreturn {best_ecom: best_alloc[ecom],best_store: best_alloc[store],best_private: best_alloc[private],max_profit: best_profit,all_results: all_results,}def profit_contribution_breakdown(allocation: dict,profiles: dict,sell_through_rates: dict) - list:拆解各渠道对总利润的贡献breakdown []for key in [ecom, store, private]:profile profiles[key]stock allocation[key]expected_sales int(stock * sell_through_rates[key])profit profile.profit_per_unit(expected_sales)breakdown.append({channel: profile.name,stock: stock,expected_sales: expected_sales,profit: round(profit, 2),margin_per_unit: round(profile.unit_margin(), 2),})return breakdown4️⃣ 结果输出reporter.py# reporter.py# 格式化输出优化结果def print_optimal_allocation(result: dict, total_inventory: int):print(\n *55)print( 最优库存分配方案)print(*55)print(f 电商库存: {result[best_ecom]:6} 件 f({result[best_ecom]/total_inventory*100:.1f}%))print(f 门店库存: {result[best_store]:6} 件 f({result[best_store]/total_inventory*100:.1f}%))print(f 私域库存: {result[best_private]:6} 件 f({result[best_private]/total_inventory*100:.1f}%))print(f\n 预计最大净利润: {result[max_profit]:.2f} 元)def print_profit_breakdown(breakdown: list, total_profit: float):print(f\n{*55})print( 各渠道利润贡献拆解)print(*55)print(f {渠道:10} {库存:8} {预计销量:10} {利润:12} {占比:8})print(f {-*52})for b in breakdown:pct (b[profit] / total_profit * 100) if total_profit 0 else 0print(f {b[channel]:10} {b[stock]:8} {b[expected_sales]:10} f{b[profit]:12.2f} {pct:.1f}%)def print_comparison_with_baseline(optimal: dict,baseline: dict,total_inventory: int):对比优化方案与基准方案如平均分配print(f\n{*55})print( 优化方案 vs 基准方案对比)print(*55)baseline_profit baseline[profit]opt_profit optimal[max_profit]lift ((opt_profit - baseline_profit) / baseline_profit * 100)lift round(lift, 2) if baseline_profit 0 else 0print(f 基准利润: {baseline_profit:.2f} 元)print(f 优化利润: {opt_profit:.2f} 元)print(f 利润提升: {lift}%)# 比例变化for ch in [ecom, store, private]:base_pct baseline[ch] / total_inventory * 100opt_pct optimal[fbest_{ch}] / total_inventory * 100print(f {ch} 占比: {base_pct:.0f}% → {opt_pct:.0f}% f(Δ{opt_pct - base_pct:.0f}%))5️⃣ 主程序main.py# main.pyimport yamlfrom modules.channel import build_channel_profilesfrom modules.optimizer import (find_optimal_allocation,profit_contribution_breakdown,)from modules.constraints import apply_capacity_constraintsfrom modules.reporter import (print_optimal_allocation,print_profit_breakdown,print_comparison_with_baseline,)def load_cfg(path: str) - dict:with open(path, r, encodingutf-8) as f:return yaml.safe_load(f)if __name__ __main__:cfg load_cfg(config/allocation.yaml)total_inv cfg[inventory][total_units]unit_cost cfg[product][unit_cost]# 构建渠道模型profiles build_channel_profiles(unit_cost)# 应用渠道专属售价/费率覆盖从配置文件if price_overrides in cfg:for ch, price in cfg[price_overrides].items():if ch in profiles:profiles[ch].selling_price priceif platform_fee_rates in cfg:for ch, rate in cfg[platform_fee_rates].items():if ch in profiles:profiles[ch].variable_cost_per_unit (profiles[ch].selling_price * rate)# 售罄率sell_through cfg[sell_through_rates]# 约束边界constraints apply_capacity_constraints(profiles, total_inv)print(*55)print( 全渠道库存分配优化引擎)print(*55)print(f\n总库存: {total_inv} 件 | 单件成本: {unit_cost} 元)print(f步长: {cfg[optimization][step]} 件)# 搜索最优方案result find_optimal_allocation(total_inventorytotal_inv,profilesprofiles,sell_through_ratessell_through,stepcfg[optimization][step])# 基准方案平均分配base_per total_inv // 3remainder total_inv - base_per * 3baseline {ecom: base_per (1 if remainder 0 else 0),store: base_per (1 if remainder 1 else 0),private: total_inv - (base_per * 2 min(remainder, 2)),profit: 0.0, # will be calculated below}baseline[profit] sum(profiles[ch].profit_per_unit(int(baseline[ch] * sell_through[ch]))for ch in [ecom, store, private])# 利润拆解breakdown profit_contribution_breakdown({ecom: result[best_ecom],store: result[best_store],private: result[best_private],},profiles,sell_through)# 输出print_optimal_allocation(result, total_inv)print_profit_breakdown(breakdown, result[max_profit])print_comparison_with_baseline(result, baseline, total_inv)6️⃣ 配置文件config/allocation.yaml# 全渠道库存分配配置inventory:total_units: 3000 # 本季新品总库存product:unit_cost: 120 # 单件生产成本元price_overrides:ecom: 279.0 # 电商促销价store: 459.0 # 门店正价private: 349.0 # 私域会员价platform_fee_rates:ecom: 0.10 # 电商平台扣点 10%store: 0.00 # 门店无平台扣点private: 0.03 # 小程序手续费 3%sell_through_rates:ecom: 0.88 # 电商售罄率 88%流量大store: 0.55 # 门店售罄率 55%客流有限private: 0.72 # 私域售罄率 72%精准用户optimization:step: 50 # 遍历步长调小→更精确调大→更快六、README.md# 线上线下多渠道利润分配与备货平衡算法教学级全渠道库存优化工具用于求解电商、实体店、私域三渠道的最优备货比例。## 功能特点- 三渠道独立利润模型含平台扣点、门店摊销、私域低成本- 遍历搜索法寻找净利润最大化分配方案- 自动校验门店最低陈列量、电商最大承载量等约束- 利润贡献拆解 优化方案 vs 基准方案对比## 使用方法bashpip install pyyamlpython main.py## 适用对象- 时尚产业与品牌创新课程全渠道战略模块- 零售供应链管理教学案例- 利润优化与资源分配建模练习七、USAGE.md使用说明# 使用说明## 核心参数说明### inventory- total_units季度总可用库存件### product- unit_cost单件生产成本含面料加工物流### price_overrides- 各渠道售价通常门店 私域 电商### platform_fee_rates- 电商平台扣点通常 5%~15%- 门店0自有渠道- 私域小程序手续费通常 1%~3%### sell_through_rates关键变量- 电商高0.80~0.95流量驱动- 门店中低0.40~0.65受选址影响大- 私域中高0.60~0.80精准触达### optimization- step遍历步长默认 50 件可调至 10 提高精度## 典型实验### 实验 1售罄率敏感性- 将门店 sell_through 从 0.40 逐步调至 0.70- 观察门店库存占比的变化趋势### 实验 2平台扣点冲击- 将电商 platform_fee_rate 从 0.05 调至 0.20- 分析电商利润贡献是否被压缩### 实验 3总库存弹性- 将 total_units 从 1000 调到 10000- 观察最优比例是否收敛到某个黄金比例## 输出解读- 最优分配净利润最大化的备货比例- 利润贡献拆解哪个渠道是利润奶牛- 基准对比优化方案比平均分配多赚多少八、核心知识点卡片┌──────────────────────────────────────┐│ 全渠道利润模型 ││ 每个渠道有独立的成本结构和售价体系 ││ 不能一刀切地比较 │└──────────────────────────────────────┘┌──────────────────────────────────────┐│ 约束优化Constraint Optimization ││ 在总量守恒 业务约束下寻找最优解 ││ 是运筹学的核心问题 │└──────────────────────────────────────┘┌──────────────────────────────────────┐│ 遍历搜索法 ││ 小变量空间下最直观的优化方法 ││ 教学价值高工程可用 SciPy 替代 │└──────────────────────────────────────┘┌──────────────────────────────────────┐│ 售罄率是分配的核心杠杆 ││ 同样 1000 件售罄率差 20% ││ 利润差距可能是倍数级的 │└──────────────────────────────────────┘九、总结中立立场本程序构建了一个结构化的全渠道库存分配决策框架- 核心洞察 1电商虽然量大但平台扣点会侵蚀利润门店虽然售罄率低但单件贡献毛利往往最高- 核心洞察 2售罄率sell_through_rate是影响分配方案的最敏感变量——提高门店 10% 售罄率可能比多备 200 件更有价值- 核心洞察 3优化分配比平均分配通常能带来 5%~25% 的利润提升差距来自把货放到能卖出去的地方需要强调的是- 本模型为教学简化未考虑跨渠道库存调拨、退货率、季节波动- 售罄率需结合历史数据或行业报告审慎估算- 遍历步长step影响精度与速度的平衡该程序适合用于- 时尚产业与品牌创新课程中的全渠道战略与供应链管理模块- 零售利润优化与资源分配的教学案例- Python 优化算法与约束建模的编程练习如需进一步扩展可加入- 线性规划求解器SciPy optimize替代遍历提升效率- 跨渠道转移成本模型如门店→电商退货的物流损耗- 多品类并行优化不同品类有不同最优比例- Matplotlib 可视化利润热力图电商占比 × 门店占比 → 利润利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛