Supply Planning Parameters — Business Guide¶
This guide explains every supply-planning parameter from a business operations perspective: what real-world problem each setting addresses, how the engine uses it to solve that problem, and when you should change it.
Service level targets, safety stock and z-score are managed exclusively in MEIO / IO and are not covered here.
Planning Horizon¶
Planning Horizon (horizon_weeks)¶
Business problem: You need replenishment orders to cover the right time window. Too short and you miss future demand spikes; too long and you commit to unreliable long-term forecasts.
How the engine uses it: The supply engine looks ahead only this many weeks when calculating projected inventory and generating replenishment recommendations. Demand forecasts, safety stock and capacity data must all cover at least this window.
How to set it: - Match your physical replenishment cycle. If you place orders every 13 weeks, use 13. - If your longest lead time is 8 weeks and you review monthly, use at least 12. - Maximum: the shorter of your forecast horizon or the capacity data horizon.
When to change it: - ↓ Decrease when forecast accuracy drops beyond a certain week — prevents overcommitment to unreliable signals. - ↑ Increase when entering a seasonal ramp-up where early commitment secures supplier capacity.
Firm Freeze Period (firm_weeks)¶
Business problem: Just-placed supply plans change every run because the forecast shifted slightly. Buyers and suppliers lose confidence in the system because "yesterday's plan is already wrong."
How the engine uses it: Inside the frozen window, the engine will not create any new planned orders. Existing firm orders and confirmed receipts in that window are still honoured. The frozen portion of the plan is stable across consecutive runs.
How to set it: - Equal to or longer than your supplier acknowledgment/firming lead time. - If it takes 2 weeks to get a PO confirmed, set at least 2. - Common values: 0 (no freeze, agile environments), 2–4 (manufacturing), 4–8 (long-lead purchasing).
When to change it: - ↑ Increase when suppliers complain about plan volatility or when PO cancellations carry penalties. - ↓ Decrease when your organisation is operationally agile and can absorb last-minute changes.
Block per Order Type (firm_orders_block_horizon)¶
Business problem: You have multiple order types (e.g. standard, express, bulk) and the engine keeps creating overlapping recommendations for the same type, causing confusion about which one is real.
How the engine uses it: When ON, the engine will not create any new recommendation for a given (item, site, order_type) before the latest existing firm order of that same type. Other order types in that window are still allowed.
How to set it: Enable when you use order-type-specific lanes or contracts and want each lane to respect its own firm baseline.
When to change it: - Enable when you see duplicate recommendations for the same order type within the firm horizon. - Disable when you want the engine to treat all orders as fungible regardless of type.
Respect Lead Time (respect_lead_time)¶
Business problem: The engine recommends orders that arrive before they could physically be received — setting false expectations for the warehouse and creating phantom shortage alerts.
How the engine uses it: When ON, no recommendation can be created inside the minimum lead-time window for that order type and item-site. The engine simply skips those weeks and places the order earlier.
How to set it: Almost always ON. Only disable in exceptional cases where you hand-edit all arrival dates.
Consolidation Window (consolidation_window)¶
Business problem: You receive many tiny orders for the same route within a few weeks, driving up administrative and shipping cost per unit.
How the engine uses it: Orders for the same route that fall within N weeks of each other are merged into a single larger order. The merged quantity is the sum, and the receipt date is the earlier of the two.
How to set it:
- 0 = disabled (never merge).
- 1–2 = light consolidation for high-frequency review cycles.
- 3–4 = aggressive consolidation when ordering cost is high relative to holding cost.
- Rule of thumb: (ordering_cost / weekly_demand_value) vs holding_cost_pct / 52. If ordering cost dominates, increase the window.
When to change it: - ↑ Increase when procurement complains about too many small POs. - ↓ Decrease when you need granular just-in-time replenishment.
Lost Sale Period (lost_sale_period_days)¶
Business problem: Some firm demand is time-critical (e.g. event-based, contractual deadline). If stock cannot arrive before the deadline, the customer cancels — yet the engine keeps generating unneeded replenishment orders for the original quantity.
How the engine uses it: Firm demand whose required date is closer than this many days, and which cannot be replenished in time, is flagged as a lost sale — the demand is removed from the supply plan and no replenishment is created for it.
How to set it: - 0 = disabled (never treat demand as lost). - Use the maximum number of days your customers will wait before cancelling or substituting. - Example: if event-related demand is firm only 14 days ahead and cancellations happen after day 7, set to 7.
When to change it: - ↑ Increase when you observe the engine generating orders for demand that already cancelled. - ↓ Decrease when you want to retain all demand regardless of lateness (e.g. backorder culture).
Forecast & Netting¶
Netting Forecast Type (netting_forecast_type)¶
Business problem: Confirmed orders (sales orders, bookings) consume against the forecast to produce net demand. But which forecast should they consume — statistical, causal, blended?
How the engine uses it: Determines which forecast stream is used as the baseline for the netting pass. - stat = best statistical forecast. - causal = engineering-driven forecast (e.g. fleet-driven failure rates). - blended = weighted combination of all active forecasts.
How to set it: - stat is the safe default for most businesses. - causal when your causal inputs ( fleet size, usage hours) are more reliable than historical demand patterns. - blended when both signals are strong and you want to hedge against either one being wrong.
When to change it: Switch to causal or blended when you systematically see over- or under-consumption against the statistical forecast in the Netted Forecast review screen.
Forward Fence (forward_fence)¶
Business problem: A large confirmed order arrives and wipes out 20 weeks of forecast in one go, leaving the statistical forecast artificially low for the rest of the horizon.
How the engine uses it: Limits how many weeks into the future a confirmed order is allowed to consume forecast. Beyond this fence, consumption stops and the remaining forecast is preserved intact.
How to set it: Roughly 2–3 times your average order lead time. If most orders cover the next 4 weeks, set 8–12.
When to change it: - ↑ Increase when single large orders legitimately cover many future periods (e.g. annual maintenance contracts). - ↓ Decrease when you see consumption spikes that distort the remaining forecast profile.
Backward Fence (backward_fence)¶
Business problem: A very old confirmed order (e.g. backdated from last quarter) is still consuming forecast in the current horizon, creating a phantom demand gap today.
How the engine uses it: Limits how many weeks into the past a confirmed order can consume forecast. Prevents stale orders from distorting current net demand.
How to set it: Equal to your longest plausible backdating window. Most businesses use 4–8 weeks.
When to change it: - ↑ Increase if your order-entry process legitimately backdates (e.g. batch uploads). - ↓ Decrease if you see old orders wiping out current-period forecast.
Capacity & Sources¶
Capacity Enforcement (capacity_enforcement)¶
Business problem: Your factory or supplier has a hard weekly limit, but the engine generates orders that exceed it — creating plans that cannot be executed.
How the engine uses it:
- soft = orders beyond capacity are still created, but a CapacityExceeded exception is raised. Use when you want visibility into capacity gaps without blocking the plan.
- hard = orders beyond capacity are blocked. The unmet quantity is left unplanned (will show as a shortage).
- none = capacity is ignored entirely.
How to set it: - Start with soft during implementation to identify where capacity constraints actually bite. - Move to hard once you have reliable capacity data and want realistic executable plans. - none only during proof-of-concept or when capacity is genuinely infinite (rare).
When to change it: Switch from soft to hard when you stop seeing actionable exceptions and the business is ready to accept that some demand simply cannot be met within the current capacity envelope.
Soft Cap Multiplier (soft_capacity_multiplier)¶
Business problem: Your base capacity is 1,000 units/week, but with overtime/ weekend shifts you can stretch to 1,200. You want the engine to plan up to the overtime limit, not stop at the base limit.
How the engine uses it: When capacity_enforcement = "soft", the engine allows orders up to base_capacity × multiplier. Beyond that, the exception fires.
How to set it: - 0 = no overtime (base capacity is the absolute limit). - 1.2 = up to 20% overtime. - 1.5 = up to 50% overtime. - Set based on your actual contingent labour/ machine availability.
When to change it: - ↑ Increase during seasonal peaks when overtime is routinely approved. - ↓ Decrease when overtime is restricted (budget cuts, labour regulations).
Balancing Threshold (balancing_threshold)¶
Business problem: Some locations are chronically overstocked while others stock out of the same SKU. You want the engine to automatically suggest inventory redistribution.
How the engine uses it: A location's excess inventory is only considered for cross-location balancing if it exceeds (safety_stock × (1 + threshold)). Below this threshold, the location keeps its surplus.
How to set it: - 0.05 = very sensitive — balances even small surpluses. - 0.10–0.15 = moderate — only significant excess triggers balancing. - 0.30+ = conservative — only large overstock is redistributed.
When to change it: - ↓ Decrease when you want aggressive inventory pooling across your network. - ↑ Increase when transfer costs are high and you want to avoid frequent small movements.
Balancing Max % (balancing_max_pct)¶
Business problem: The engine drains a donor location completely to fill a shortage, creating a new stockout at the donor next week.
How the engine uses it: Limits the fraction of a location's excess that can be moved in a single balancing action. The remainder stays as buffer at the donor.
How to set it: - 0.3–0.5 = conservative — leaves significant buffer at the donor. - 0.7–0.9 = aggressive — moves almost all excess. - 1.0 = unlimited — moves all excess (risky if demand at donor is uncertain).
When to change it: - ↓ Decrease when donor locations have volatile demand and need protection. - ↑ Increase when the donor is a regional hub whose sole purpose is to feed spokes.
Costs & Penalties¶
Lost Sales Penalty (lost_sales_penalty)¶
Business problem: Stockouts don't just delay demand — some customers walk away permanently. This lost margin and damaged relationship has a real dollar value.
How the engine uses it: In cost-optimised planning mode, the engine weighs the cost of holding extra inventory against this penalty. If the penalty is high, the engine prefers to overstock rather than risk a lost sale.
How to set it:
- Calculate: (unit_margin + customer_lifetime_value_fraction).
- Example: unit margin = 80, estimated CLV impact = 20 → set to 100.
- If you have no data, start at 100 and adjust based on observed stockout behaviour.
When to change it: - ↑ Increase for strategic customers or high-margin SKUs where a stockout is especially damaging. - ↓ Decrease for low-margin or commoditised items where substitution is easy.
Shortage Penalty (shortage_penalty)¶
Business problem: Unmet demand creates immediate operational pain — production stoppages, expediting fees, contractual penalties.
How the engine uses it: Drives the urgency score in cost-optimised mode. Higher values make the engine prioritise eliminating shortages even if it means higher inventory or expediting cost.
How to set it:
- Calculate: (expediting_cost_per_unit + contractual_penalty_per_unit + operational_impact).
- If a shortage triggers a 500 expedite fee and a 200 SLA penalty, set to 700.
When to change it: - ↑ Increase during contract renewal periods or when SLA penalties are enforced. - ↓ Decrease when your organisation is comfortable with planned shortages (e.g. allocation-based稀缺 cultures).
Lateness Penalty (lateness_penalty_per_week)¶
Business problem: A unit that arrives 3 weeks late may technically satisfy demand, but the customer experience is degraded and downstream schedules are disrupted.
How the engine uses it: Penalises delayed fulfilment in cost-optimised scoring. Higher values push the engine toward earlier replenishment (more safety stock) to avoid lateness.
How to set it:
- Roughly (shortage_penalty / 4) as a starting point — being 4 weeks late is about as bad as being 1 unit short.
- Adjust based on how much your customers or internal teams value on-time arrival.
Holding Cost (holding_cost_pct)¶
Business problem: Carrying inventory is not free — it ties up working capital, occupies warehouse space, and risks obsolescence.
How the engine uses it: Annual holding cost as a fraction of item value. The engine uses this to find the cost-optimal trade-off between inventory investment and service/penalty costs.
How to set it: - Typical components: cost of capital (8–12%) + warehouse space (3–5%) + insurance/obsolescence (2–5%). - Total: 0.15–0.25 for most businesses. - High-tech/electronics with fast obsolescence: 0.30–0.40. - Commodities with stable value: 0.10–0.15.
When to change it: - ↑ Increase when interest rates rise or product lifecycles shorten. - ↓ Decrease when warehouse space is abundant and capital is cheap.
Expedite Cost Multiplier (expedite_cost_multiplier)¶
Business problem: Standard replenishment is cheap but slow. When a shortage threatens, you can expedite — but at a premium. The engine should only recommend expediting when the shortage penalty justifies the extra cost.
How the engine uses it: Multiplies the standard unit cost when an order is expedited (e.g. air freight, express manufacturing). The engine will only create an expedited order when the shortage/lateness penalty exceeds this extra cost.
How to set it: - 1.5 = +50% premium (common for air freight vs sea). - 2.0 = +100% premium (express manufacturing). - 3.0+ = extreme premium (charter flights, overtime workshops).
Overtime Cost Multiplier (overtime_cost_multiplier)¶
Business problem: Using soft capacity (overtime, weekend shifts) costs more than base capacity. The engine should factor this in when deciding whether to schedule beyond the hard cap.
How the engine uses it: Works with capacity_enforcement = "soft" and soft_capacity_multiplier. The portion of production scheduled in the overtime zone uses this higher cost.
How to set it: - 1.3 = +30% (typical overtime wage premium). - 1.5 = +50% (weekend shifts). - Match your actual labour cost differential.
Strategy & Performance¶
Planning Mode (planning_mode)¶
Business problem: Your organisation has conflicting goals — customer service wants zero stockouts, finance wants minimum inventory, operations wants stable schedules.
How the engine uses it: - service_optimised = minimise shortages first, accept higher inventory. The plan prioritises fill rate; cost is secondary. - cost_optimised = balance all objectives using weighted scoring. You control the trade-off via the weight parameters below.
How to set it: - service_optimised when customer availability is your competitive advantage (e.g. spare parts, medical supplies). - cost_optimised when you need explicit control over the trade-off and want to experiment with different strategies.
When to change it: Switch to cost_optimised once your supply chain is mature and you have reliable penalty/holding cost data. Start with service_optimised during initial rollout.
Service Level Weight (service_level_weight)¶
Business problem: In cost-optimised mode, you want to dial up (or down) how much the engine cares about fill rate relative to cost.
How the engine uses it: Weight for fill-rate performance in the cost-optimised scoring function. Higher = more safety stock, fewer shortages, higher inventory.
How to set it: - 0.7 = service-oriented (typical starting point). - 0.5 = balanced. - 0.3 = cost-oriented.
When to change it: Tune quarterly based on observed fill-rate vs inventory-value KPIs. If fill rate is above target, reduce weight to free up working capital.
Cost Weight (cost_weight)¶
Business problem: You want the engine to explicitly reward plans that minimise total cost (holding + ordering + expediting + penalties).
How the engine uses it: Weight for total cost in the cost-optimised scoring function. Higher = leaner inventory, more shortages accepted.
How to set it: Usually 1.0 - service_level_weight. If service = 0.7, cost = 0.3.
Lateness Weight (lateness_weight)¶
Business problem: On-time delivery matters, but not as much as having stock at all. You want to penalise lateness without making it dominate the objective.
How the engine uses it: Additional weight specifically for lateness in cost-optimised scoring. 0 = lateness is ignored (only shortage vs cost trade-off).
How to set it: - 0 = no lateness penalty (pure shortage/cost trade-off). - 0.05–0.1 = moderate — lateness matters but shortages matter more. - 0.2+ = high — on-time delivery is a strategic KPI.
Nervousness Limit (nervousness_limit)¶
Business problem: The plan changes too much between runs. Buyers can't commit to suppliers, and warehouse labour schedules are unstable.
How the engine uses it: Limits the maximum allowed change rate between consecutive planning runs. If the new plan would change a planned order by more than this fraction, the engine caps the change.
How to set it: - 0 = disabled (no limit). - 0.10 = ±10% change allowed. - 0.15 = ±15% (common for stable demand). - 0.25 = ±25% (for volatile markets).
When to change it: - ↑ Increase when demand is genuinely volatile and you want the plan to track reality closely. - ↓ Decrease when operational stability is more important than forecast-tracking precision.
Workers (workers)¶
Business problem: Supply planning runs take too long and block the pipeline, or they consume all CPU and slow down the database for other users.
How the engine uses it: Number of parallel threads the engine uses. 0 = auto-detect (uses all cores).
How to set it:
- 0 for dedicated planning servers.
- 2–4 for shared servers where you want to leave headroom.
- Never exceed (CPU_cores - 1) on a shared database node.
Sparse Threshold (sparse_threshold)¶
Business problem: Your catalogue contains thousands of SKUs with near-zero demand. Planning them wastes CPU and creates noise in the exceptions screen.
How the engine uses it: SKUs whose total forecasted demand across the entire horizon is below this threshold are skipped entirely. They receive no supply plan and generate no exceptions.
How to set it: - 0 = plan everything. - 1 = skip only truly dead items. - 5–10 = moderate filtering for large catalogues. - Review quarterly — a SKU that is sparse today may become active next season.
Pegging & Allocation¶
Pegging Mode (pegging_mode)¶
Business problem: When a shortage occurs, you need to know exactly which demand it belongs to in order to prioritise or negotiate with the customer. Without traceability, you are flying blind.
How the engine uses it: - full = every demand-supply link is traced and stored. Best traceability, highest memory and CPU cost. - partial = only recent links are kept. Balanced. - off = no traceability. Fastest, lowest memory.
How to set it: - off for very large catalogues (100K+ SKUs) unless audit trails are mandated. - full when customer-specific allocation is critical (e.g. spare parts with service contracts). - partial as the default middle ground.
Allocation Strategy (allocation_strategy)¶
Business problem: When supply is constrained, not all demand can be fulfilled. You need a transparent rule for who gets stock.
How the engine uses it: Determines prioritisation when constrained supply must be allocated across competing demands: - fifo = oldest demand first (fair, simple). - priority = critical demand first (requires priority classes on orders). - fair_share = proportional allocation (everyone gets a fraction). - expiry_first = demands with the soonest expiry date are filled first (perishables, pharma).
How to set it: - fifo for most B2B contexts. - priority when you have contractual service tiers (gold/silver/bronze customers). - fair_share when maintaining customer relationships is more important than individual order fulfilment. - expiry_first for pharmaceutical or food supply chains.
Output¶
Integer Projected Stock (integer_projected_stock)¶
Business problem: The engine calculates fractional units (e.g. 3.7 units on hand), but your ERP and warehouse systems only accept whole numbers. Rounding discrepancies cause reconciliation errors.
How the engine uses it: When ON, projected inventory values are rounded to the nearest integer before being stored in the supply plan tables. When OFF, fractional values are preserved.
How to set it: - ON for discrete items (individually tracked parts, whole units). - OFF for bulk or continuous materials (fluids, cable by the metre, commodities).
Quick-Reference Decision Matrix¶
| If your problem is... | Start with these parameters |
|---|---|
| Plans change too much run-to-run | nervousness_limit, firm_weeks |
| Too many small POs | consolidation_window |
| Stockouts despite planning | planning_mode = service_optimised, lost_sales_penalty |
| Inventory too high | planning_mode = cost_optimised, holding_cost_pct, excess_pct (MEIO) |
| Capacity exceeded every week | capacity_enforcement, soft_capacity_multiplier |
| Some locations overstock while others stock out | balancing_threshold, balancing_max_pct |
| Large orders distort the forecast | forward_fence |
| Planning run too slow | workers, sparse_threshold |
| Can't trace which demand caused a shortage | pegging_mode = full |