From Inventory Optimization to Profit: Accounting KPIs, Working Capital and Explainable Recommendations
A forecast that is accurate and an inventory policy that is efficient are still not the same as a business that is profitable. This second part adds the missing layer: turnover and accounting KPIs to measure the financial impact of inventory decisions, and explainability to show managers why the system recommends what it recommends. We continue with the same supermarket example.
- The difference between sales turnover and inventory turnover, and how GMROI, inventory days, and working capital relate to each other.
- Why fill rate and cycle service level are different, with a worked example.
- How accounting numbers (margin, cost, salvage value) set the newsvendor critical fractile.
- How to compare policies financially, including marginal returns on extra inventory.
- How to explain forecasts (SHAP), order decisions, and financial trade-offs.
1. Two meanings of "turnover"
In retail, turnover can mean two different things, and both matter.
1.1 Sales turnover: revenue
If the supermarket sells 100 units at €5, revenue is \(R_t=P_t\,S_t=5\times100=500\text{ euros}\). For several products:
$$R_t=\sum_{j=1}^{J}P_{j,t}\,S_{j,t}$$where \(j\) indexes products, \(P_{j,t}\) is the price, and \(S_{j,t}\) the units sold in period \(t\). Revenue is not profit: cost of goods, labor, waste, and financing still have to be paid. In financial statements, the exact definition also depends on VAT, discounts, and returns, so align your data with the company's reporting rules.
1.2 Inventory turnover: how fast stock sells and is replaced
$$\text{Inventory turnover}=\frac{\text{COGS}}{\text{Average inventory value (at cost)}}$$| Term | Meaning |
|---|---|
| COGS | Cost of goods sold: the accounting cost of the products sold in the period |
| Average inventory value | Average value of stock held during the period, measured at cost |
With COGS of €360,000 and average inventory of €60,000, turnover is 6: the retailer sells and replaces its stock about six times a year.
Mixed valuation: COGS is at cost, so average inventory must be at cost too, never at selling price. Crude averages: averaging only opening and closing stock misleads for seasonal products. Use monthly or daily snapshots.
Higher turnover often means less cash tied up in stock, but higher is not always better. If it is high because shelves are empty, sales are being lost. Always read turnover next to service level and profitability.
2. Accounting KPIs: connecting operations to profit
A better forecast or a lower stockout rate does not automatically raise profit. Extra inventory buys availability, but it also ties up cash. We need financial KPIs to judge each policy.
2.1 Gross profit, gross margin, and markup
A product sells at €5 and costs €3. For 100 units: revenue €500, \(COGS=c\times S=300\text{ euros}\), and:
$$GP=R-COGS=200,\text{ euros}\qquad GM=\frac{R-COGS}{R}=40\%,\qquad \text{Markup}=\frac{GP}{COGS}=\frac{200}{300}=66.7\%$$Margin and markup are easy to confuse. Margin is a share of revenue; markup is a share of cost. They are linked by \(\text{Markup}=GM/(1-GM)\). Gross profit is also not net profit: it excludes warehousing, labor, transport, and financing.
2.2 GMROI: gross profit per euro of stock
Gross Margin Return on Inventory Investment measures how much gross profit each euro of average inventory generates:
$$GMROI=\frac{\text{Gross profit}}{\text{Average inventory at cost}}$$With €120,000 of annual gross profit and €40,000 of average inventory, GMROI is 3: €3 of gross profit per €1 invested in stock. It is not a 300% net return, because it ignores all costs below gross profit.
A product earns a high GMROI through fast turnover, a fat markup, or both. This is why a low-margin product that sells very fast can beat a high-margin product that sits on the shelf.
Here is a two-product comparison (illustrative values):
| KPI | Product A | Product B |
|---|---|---|
| Annual revenue | €100,000 | €100,000 |
| COGS | €70,000 | €75,000 |
| Gross profit | €30,000 | €25,000 |
| Average inventory at cost | €10,000 | €20,000 |
| Inventory turnover | 7.0 | 3.75 |
| GMROI | 3.0 | 1.25 |
Same revenue, but A earns more gross profit with half the stock. A forecasting and replenishment system can use this to find where better decisions would free working capital. Still, treat GMROI as a performance KPI, not as the objective of every optimization: maximizing a ratio can push a model to sacrifice sales or service just to shrink the denominator.
3. Working capital: money tied up in stock
3.1 Inventory value and its carrying cost
Holding 1,000 units at €3 each means €3,000 of capital in stock: \(V=I\times c\). Cutting average stock to 700 units, without hurting sales, releases \(\Delta V=(1000-700)\times 3=900\text{ euros}\). That is cash freed, not profit earned.
Holding inventory also has a running cost, usually expressed as an annual rate \(i\) on inventory value:
$$h_{\text{year}}=c\times i,\qquad \text{where } i\text{ covers cost of capital, storage, insurance, shrinkage, obsolescence}$$At an illustrative \(i=10\%\), the €900 released saves about €90 a year. This is how the holding cost \(h\) from the simulation (Part 8 of the first guide) connects to accounting.
3.2 Inventory days and the cash conversion cycle
$$DIO=\frac{\text{Average inventory}}{COGS}\times T=\frac{T}{\text{Inventory turnover}}$$With €60,000 of average inventory, €360,000 of annual COGS, and \(T=365\): \(DIO=60{,}000/360{,}000\times365\approx60.8\) days. This equals \(365/6\), as the identity says. Cutting DIO from 60 to 30 days may be great for a predictable item with a reliable supplier, and dangerous for a seasonal item with a long lead time.
Inventory days are one piece of the cash conversion cycle:
$$CCC=DIO+DSO-DPO$$| Term | Meaning | Supermarket example |
|---|---|---|
| DIO | Days inventory outstanding | about 61 days |
| DSO | Days sales outstanding (time to collect from customers) | about 0, customers pay at checkout |
| DPO | Days payables outstanding (time to pay suppliers) | 30 days, if suppliers allow it |
| CCC | Days cash is tied up | about 31 days |
Better replenishment lowers DIO, but negotiating payment terms moves DPO. Both change how long cash is tied up, so a finance team may value them differently.
4. Service-level KPIs: the customer side
Financial metrics alone can mislead. A retailer can raise turnover and release cash simply by running out of stock. Operational KPIs keep the optimization honest.
4.1 Fill rate and unmet demand
$$\text{Fill rate}=\frac{\text{Units fulfilled immediately}}{\text{Units demanded}},\qquad \text{Unmet-demand rate}=\frac{\text{Unmet units}}{\text{Units demanded}}$$If customers demand 1,000 units in a week and 950 are supplied immediately, the fill rate is 95% and the unmet-demand rate is 5%. For these unit-based definitions they sum to 100%. Other metrics called "stockout rate" may not: a stockout-event rate, for instance, counts the share of product-days with zero stock. Some companies also measure fill rate on order lines rather than units. Always state the definition.
4.2 Cycle service level is not fill rate
These two are often mixed up, and they can differ a lot:
$$\text{CSL}=P(D\leq S),\qquad \beta=1-\frac{\mathbb{E}[(D-S)^+]}{\mathbb{E}[D]}$$CSL is the probability of no stockout in a cycle. The fill rate \(\beta\) is the share of units served, so it depends on how large the shortages are, not just how often they happen. For normal demand, \(\mathbb{E}[(D-S)^+]=\sigma\,L(z)\) with \(z=(S-\mu)/\sigma\) and \(L(z)=\varphi(z)-z\,(1-\Phi(z))\), where \(\varphi\) and \(\Phi\) are the standard normal density and CDF.
Single period, demand \(\mathcal{N}(100,20^2)\), stock \(S=130\). Then \(z=1.5\), so CSL \(=\Phi(1.5)=93.3\%\). The loss function is \(L(1.5)=0.1295-1.5\times0.0668=0.0293\), so expected shortage is \(20\times0.0293=0.59\) units, and:
$$\beta=1-\frac{0.59}{100}\approx99.4\%$$The same stock gives a 93.3% chance of no stockout, but 99.4% of units are served.
This is why the constraint in an optimization problem must name its metric. \(\operatorname{FillRate}(\pi)\geq0.95\) and \(\operatorname{CSL}(\pi)\geq0.95\) lead to very different inventory levels.
5. A KPI dashboard in three groups
| Group | KPI | Definition |
|---|---|---|
| Financial performance | Revenue | Price × units sold |
| Gross profit and margin | Revenue − COGS; gross profit ÷ revenue | |
| GMROI | Gross profit ÷ average inventory at cost | |
| Inventory-related costs | Holding, ordering, waste, markdowns | |
| Capital efficiency | Average inventory value | Average units × unit cost |
| Inventory turnover | COGS ÷ average inventory at cost | |
| Inventory days | Average inventory ÷ COGS × days in period | |
| Operational performance | Fill rate | Units fulfilled immediately ÷ units demanded |
| Stockout frequency | Share of product-days with zero stock | |
| Waste rate | Wasted units ÷ relevant quantity base | |
| Supplier lead-time performance | Actual versus promised lead times |
Tracking all three groups stops a model from looking successful by improving one metric while damaging another.
6. How accounting numbers set the critical fractile
In the first guide, the newsvendor order is the quantile \(\tau^*=C_u/(C_u+C_o)\). Accounting data tells you what \(C_u\) and \(C_o\) are:
$$C_u=\underbrace{p-c}_{\text{lost unit margin}}+g,\qquad C_o=\underbrace{c-s}_{\text{loss on a leftover unit}}+h$$where \(p\) is price, \(c\) unit cost, \(s\) salvage value of a leftover unit (markdown or resale), \(g\) a goodwill cost of disappointing a customer, and \(h\) holding cost.
| Case | \(C_u\) | \(C_o\) | Critical fractile |
|---|---|---|---|
| Fresh item, €5 price, €3 cost, no salvage | 2 | 3 | 0.40 |
| Same item, markdown salvage of €2.50 | 2 | 0.50 | 0.80 |
| Fresh item, no salvage, €1 goodwill cost | 3 | 3 | 0.50 |
This is a useful result for managers: a product with thin margin and no resale value should be stocked below median demand, even though it will sometimes sell out. A product with good margin or an easy markdown deserves a large buffer. It also shows that one service-level target for every product is rarely optimal. These formulas assume a single period; in multi-period lost-sales systems, a stockout also costs future sales, which raises \(C_u\).
7. Putting KPIs inside the simulation
For each simulated period, we compute revenue \(R_t=\sum_jP_{j,t}S_{j,t}\), gross profit \(GP_t=R_t-COGS_t\), and the inventory-related cost:
$$C_{\text{inventory}}=C_{\text{holding}}+C_{\text{ordering}}+C_{\text{shortage}}+C_{\text{waste}}$$If gross profit is already computed after lost sales, do not subtract the lost revenue again as a shortage cost. Decide whether \(C_{\text{shortage}}\) represents an extra economic cost (such as customer dissatisfaction) or a substitute for the lost margin, and use only one.
7.1 Two policies compared
Policy A is conservative: smaller orders, less stock, more stockout risk. Policy B is availability-focused: larger orders, more stock, fewer stockouts. Hypothetical annual simulation results:
| KPI | Policy A | Policy B |
|---|---|---|
| Revenue | €500,000 | €520,000 |
| COGS | €350,000 | €364,000 |
| Gross profit | €150,000 | €156,000 |
| Average inventory at cost | €50,000 | €70,000 |
| Inventory turnover (COGS ÷ inventory) | 7.0 | 5.2 |
| GMROI (gross profit ÷ inventory) | 3.0 | 2.23 |
| Fill rate | 91% | 97% |
| Inventory-related costs outside COGS | €15,000 | €18,000 |
| Gross profit minus those costs | €135,000 | €138,000 |
Note which numerator each KPI uses: turnover uses COGS, GMROI uses gross profit. Mixing them up is a classic bug in KPI pipelines; \(364{,}000/70{,}000=5.2\) while \(156{,}000/70{,}000=2.23\).
Policy B wins on revenue, gross profit, fill rate, and net contribution (by €3,000). Policy A wins on turnover, GMROI, and capital use. Which is better depends on constraints and the cost of capital.
7.2 Marginal analysis: is the extra inventory worth it?
Moving from A to B adds €20,000 of stock and €6,000 of gross profit, a marginal return of 0.30 per euro invested, before costs. After the extra €3,000 of costs, it is €3,000 on €20,000, a 15% return on the additional capital. If the cost of capital is not already inside those costs and is, say, 10%, subtract \(0.10\times20{,}000=2{,}000\text{ euros}\): B's advantage shrinks from €3,000 to €1,000. The comparison with the cost of capital is what decides.
Returns usually diminish. Take three target levels (hypothetical):
| Target inventory | Gross profit | Average inventory | Fill rate |
|---|---|---|---|
| 100 units | €150,000 | €50,000 | 91% |
| 115 units | €153,000 | €58,000 | 94% |
| 130 units | €156,000 | €70,000 | 97% |
7.3 Computing the KPIs in code
def kpis(revenue, cogs, avg_inventory_cost, units_demanded,
units_fulfilled, other_costs, days=365):
gp = revenue - cogs
return {
"gross_profit": gp,
"gross_margin": gp / revenue,
"inventory_turnover": cogs / avg_inventory_cost,
"inventory_days": days * avg_inventory_cost / cogs,
"gmroi": gp / avg_inventory_cost,
"fill_rate": units_fulfilled / units_demanded,
"contribution": gp - other_costs,
}
# Policy A from the table: turnover 7.0, GMROI 3.0, contribution 135,000
print(kpis(500_000, 350_000, 50_000, 100_000, 91_000, 15_000)) 8. Explainability, level 1: why this demand forecast?
Managers will ask: why is demand so high for this product? Why order 150 and not 100? Why did GMROI drop while fill rate improved? There are three different things to explain, and they should not be confused: the forecast, the order decision, and the financial consequences.
8.1 SHAP values for a quantile forecast
SHAP splits one prediction into a baseline plus a contribution from each feature:
$$f(x)=\phi_0+\sum_{j=1}^{p}\phi_j$$where \(\phi_0\) is the baseline prediction (the average over the reference data), \(p\) the number of features, and \(\phi_j\) the contribution of feature \(j\) for this instance. Suppose the model predicts the 80th percentile of demand, \(\hat Q_{0.80}(x)=130\), with a baseline of 100:
| Feature | Contribution |
|---|---|
| Baseline prediction | 100 |
| Active promotion | +18 |
| Weekend | +8 |
| Recent sales trend | +10 |
| Higher price | −6 |
| Prediction | 130 |
import shap
explainer = shap.TreeExplainer(models[0.80]) # explain the 0.80 quantile model
phi = explainer.shap_values(X_row) # shape (1, n_features)
base = float(np.ravel(explainer.expected_value)[0])
print(base + phi.sum(), models[0.80].predict(X_row)) # the two should match - It explains how the trained model produces a prediction. It does not prove that the promotion caused the extra demand.
- Explain the specific quantile being used. The promotion may add 18 units at Q0.80 but far more at Q0.95, because promotions also widen uncertainty. For a quantile-conditioned model \(f_\theta(x,\tau)\), state the \(\tau\) being explained.
- Strongly correlated features (price and promotion, for example) share credit in ways that can surprise people. Say so when presenting.
- Per-prediction (local) SHAP values explain one decision. Averaging their absolute values over time (global importance) is also a useful monitoring signal.
9. Explainability, level 2: why this order quantity?
Suppose the forecast says 130 but the system orders 75. This is not a contradiction: the forecast estimates demand, while the order depends on what you already have. With a target of 130 and an inventory position of 55:
$$O_t=\max(0,\,S-IP_t)=\max(0,\,130-55)=75$$SHAP explains the forecast; it does not explain this step. For decisions, expose the policy logic itself:
The model estimates an 80th-percentile demand of 130 units for the planning period. The current inventory position is 55 units (35 on hand, 20 on order). Under the order-up-to policy, the target is 130, so the system recommends ordering 75 units. The 80th percentile comes from the chosen cost and service-level assumptions.
10. Explainability, level 3: why is this financially attractive?
A manager may object: "Inventory turnover is going down, so why hold more stock?" The answer must rest on measured trade-offs. Compare the proposed policy with a baseline:
$$\Delta KPI=KPI_{\text{new}}-KPI_{\text{baseline}}$$From the table in section 7.2, moving from target 100 to 130 changes gross profit by \(\Delta GP=6{,}000\text{ euros}\), inventory by \(\Delta V=20{,}000\text{ euros}\), and fill rate by six percentage points. A counterfactual explanation puts it in words:
Raising the target from 100 to 130 units is estimated to add €6,000 of annual gross profit and six points of fill rate, while adding €20,000 of average inventory. An intermediate target of 115 units gets half of that gross profit gain with €8,000 of extra stock.
Managers often find this more useful than a feature-importance chart. But these figures must come from a properly designed simulation or backtest, and they are estimates, not guarantees. A change in gross profit is also not a change in net profit: include every relevant incremental cost.
11. Explainability, level 4: how reliable is it?
A recommendation is more useful with its uncertainty attached. Report the distribution of each KPI across simulated scenarios (for example the 10th to 90th percentile), not just the mean. Then stress the assumptions that matter most:
| Sensitivity test | What changes | Question answered |
|---|---|---|
| Lead time +1 day | Supplier delay | Does fill rate stay above the target? |
| Demand +10% or −10% | Forecast bias | How fragile is the order-up-to level? |
| Cost of capital doubled | Financing environment | Does the higher-stock policy still pay? |
The four levels together:
| Level | Question | Method |
|---|---|---|
| Forecast | Why this demand quantile? | SHAP, feature analysis, calibration checks |
| Decision | Why this order quantity? | Explicit policy rules, inventory-position breakdown, constraints |
| Financial | Why is it attractive? | KPI deltas, counterfactual scenarios, marginal analysis |
| Uncertainty | How reliable is it? | Scenario distributions, intervals, sensitivity tests |
Instead of "Recommended order: 130 units", the system can say: "Target 130 (80th-percentile demand), driven mainly by the promotion and recent trend. Inventory position is 55, so order 75. Simulation estimates a 97% fill rate versus 91% under the current policy, with uncertainty from demand variability and model error."
12. A fuller optimization objective
The first guide minimized expected cost. A retailer may prefer to maximize expected profit under operational limits:
$$\max_{\pi\in\Pi}\ \mathbb{E}\bigl[R(\pi)-COGS(\pi)-C_{\text{other}}(\pi)\bigr]\quad\text{s.t.}\quad \operatorname{FillRate}(\pi)\geq\alpha,\quad \mathbb{E}[V_{\text{inventory}}(\pi)]\leq B$$| Symbol | Meaning |
|---|---|
| \(\pi\), \(\Pi\) | An inventory policy and the set of feasible policies |
| \(R(\pi)\), \(COGS(\pi)\) | Revenue and cost of goods sold under \(\pi\) |
| \(C_{\text{other}}(\pi)\) | Other relevant costs: holding, ordering, waste, shortage |
| \(\alpha\) | Minimum required fill rate |
| \(V_{\text{inventory}}(\pi)\), \(B\) | Inventory value under \(\pi\), and the permitted maximum |
Turnover and GMROI work better as constraints, reporting metrics, or secondary objectives than as terms in one weighted score. Otherwise the optimizer may exploit the chosen KPI at the expense of overall value.
With thousands of products sharing a budget \(B\), the best allocation equalizes the marginal gross profit per euro of stock across products: \(\partial\,\mathbb{E}[GP_j]/\partial V_j\approx\lambda\) for every product \(j\) that gets stock, where \(\lambda\) is the shadow price of the budget. Figure 5 is that idea for one product: stop adding stock when the next euro earns less than \(\lambda\), or less than your cost of capital.
13. Implementing it as a data science project
- Data engineering: reconcile sales, catalog, prices, promotions, inventory snapshots, purchase orders, lead times, product costs, and accounting data under consistent product IDs, periods, and cost definitions.
- Forecasting: a point baseline, quantile models, and optionally a full distributional model, validated on held-out data.
- Inventory simulation: demand scenarios, stock, replenishment, lead times, lost sales or backorders, holding, ordering, and waste costs.
- Policy optimization: search reorder points, order-up-to levels, service targets, and order quantities under the constraints above.
- KPI computation: revenue, gross profit and margin, turnover, inventory days, GMROI, average inventory value, fill rate, stockout and waste metrics, all matching the company's reporting.
- Explainability and monitoring: for each recommendation, show the forecast and its quantile, top features, inventory position, policy and constraints, order quantity, expected KPI changes versus baseline, and uncertainty.
Monitoring should include:
- Forecast calibration: does the Q0.80 forecast cover about 80% of actual outcomes, by product group?
- Bias and drift: forecast error over time, and changes in feature distributions or SHAP importance.
- Simulation versus reality: compare realized fill rate, turnover, and gross profit with what the simulator predicted.
- Overrides: log when planners reject a recommendation, and why. Patterns in overrides often reveal missing constraints.
- Censored demand: track stockout days so that low sales caused by empty shelves are not mistaken for low demand when retraining.
- Historical sales, inventory, and accounting data.
- Demand forecasting and quantile estimation.
- Inventory policy and stochastic simulation.
- Financial and operational KPI evaluation.
- Policy optimization under business constraints.
- Explainable recommendations and monitoring.
14. Final perspective
With accounting KPIs and explainability, the project becomes a decision-support system for retail operations and financial performance:
The key principle is that forecast accuracy, inventory efficiency, and financial performance are related but not interchangeable. A good forecast estimates demand reliably, a good policy turns it into sensible orders, a good simulation measures the consequences, accounting KPIs quantify the business impact, and explainability lets managers understand and trust the result.
Comments
Post a Comment