Supply Chain & Sourcing Intelligence
Fashion Demand Forecasting, Supplier Quality Scoring, and Tirupur Export Logistics
The Textile Supply Chain as a Signal Processing Problem
India's apparel export supply chain — from cotton fields in Maharashtra and Gujarat through spinning in Coimbatore, weaving or knitting in Surat and Tirupur, dyeing in Erode and Bhilwara, and garment manufacturing in Bengaluru, NCR, and Tirupur — spans 6–9 weeks of lead time under normal conditions. Demand signals from a buyer in Stockholm or New York arrive at Tirupur export houses with varying reliability and lead time. The AI task is not to eliminate this lead time but to extract the maximum information from early-stage demand signals to pre-position raw materials and capacity — reducing confirmed-order-to-ship time from 60–75 days to 35–45 days.
Open data/tirupur-order-history.csv in the code panel. It contains 3 years of order records from 8 Tirupur export houses — buyer, product category, quantity, delivery window, actual ship date, fabric source (local vs. import), and penalty clause trigger events — covering approximately 4,200 export orders to EU, US, and Australian buyers.
Fashion Demand Forecasting Architecture
Hierarchy and Granularity
Apparel demand forecasting operates across multiple hierarchical levels simultaneously:
| Level | Granularity | Forecast Horizon | Primary Driver |
|---|---|---|---|
| Season/collection | Style group | 6–12 months | Buyer NOS (Next Order Signals), fashion intelligence |
| Initial buys | Style × size × colour | 3–4 months | Buyer commitment, historical sell-through |
| In-season replenishment | SKU × location | 2–6 weeks | POS sell-through, inventory depletion rate |
| Raw material pre-buy | Fabric quality × colour family | 4–8 months | Forecast uncertainty + supplier lead time |
The reconciliation challenge: a bottom-up SKU-level forecast sums to a different number than a top-down season-level forecast. Probabilistic reconciliation (using the hierarchicalforecast library) forces coherence across levels while propagating forecast uncertainty correctly.
Cotton Price Volatility as a Forecasting Input
Indian cotton prices (NCDEX MCX futures, also tracked by CAI's Cotton Outlook) contribute to input cost volatility that affects sourcing decisions independently of demand. The correlation between Shankar-6 prices and Tirupur export house margin compression is well-documented in AEPC (Apparel Export Promotion Council) data.
import pandas as pd
import numpy as np
from statsmodels.tsa.statespace.varmax import VARMAX
def build_cotton_demand_var(
cotton_price_series: pd.Series, # weekly MCX Shankar-6 futures (INR/quintal)
order_volume_series: pd.Series, # weekly new order commitments (lakh pieces)
n_lags: int = 8
) -> VARMAX:
"""
Vector Autoregression for cotton price × order volume interaction.
8 lags = 8 weeks captures the typical booking-to-fabric-purchase cycle.
"""
df = pd.DataFrame({
"cotton_price": cotton_price_series,
"order_volume": order_volume_series
}).dropna()
model = VARMAX(df, order=(n_lags, 0))
return model.fit(disp=False)The VAR impulse response function reveals how an ₹800/quintal cotton price spike (similar to the 2021–22 spike that hit ₹98,000/candy) propagates to order volume: typically a 3–4 week lag before buyers reduce order depth in price-sensitive categories (t-shirts, basic hosiery) while maintaining volume in value-added (printed, embroidered) categories.
Supplier Quality Scoring
Defining the Score
For a Tirupur export house sourcing greige fabric from 12–15 Coimbatore mills and Surat weavers, supplier quality scoring must go beyond defect rate to include delivery reliability and communication responsiveness:
from dataclasses import dataclass
@dataclass
class SupplierScoreWeights:
defect_rate_pct: float = 0.35 # % lots rejected or returned
on_time_delivery: float = 0.25 # % shipments within ±2 days of committed date
shade_consistency: float = 0.20 # ΔE CIE2000 variation across lots (same shade)
gsm_tolerance: float = 0.10 # % lots within ±5% of ordered GSM
documentation_compliance: float = 0.10 # TC, test reports, packing lists on time
def compute_supplier_score(metrics: dict, weights: SupplierScoreWeights) -> float:
"""
metrics: {defect_rate_pct, on_time_delivery_pct, mean_delta_e_variation,
gsm_tolerance_pct, doc_compliance_pct}
Returns 0–100 score; > 75 = approved, 60–75 = conditional, < 60 = probation.
"""
score = (
(100 - metrics["defect_rate_pct"] * 10) * weights.defect_rate_pct +
metrics["on_time_delivery_pct"] * weights.on_time_delivery +
max(0, 100 - metrics["mean_delta_e_variation"] * 25) * weights.shade_consistency +
metrics["gsm_tolerance_pct"] * weights.gsm_tolerance +
metrics["doc_compliance_pct"] * weights.documentation_compliance
)
return round(score, 1)Sourcing Decision Support
Prompt: "I have quality score data for 14 fabric suppliers across 6 months. The top 3 suppliers
(scores 82, 79, 77) are all at capacity for the next 8 weeks due to festival season orders.
My next confirmed order is 45,000 metres of 180 GSM cotton interlock for an EU buyer with
GOTS certification requirement, delivery in 38 days. Three mid-tier suppliers (scores 68, 65, 71)
have capacity. Supplier A (68) has GOTS certification but had 3 shade consistency failures in
the last quarter. Supplier B (65) is GOTS certified and reliable but requires 10% advance payment.
Supplier C (71) is not GOTS certified but offered the best price. Walk me through a sourcing
risk matrix for this order and recommend the optimal decision, including risk mitigation steps."Fabric-to-Garment Lead Time Modelling
The critical path in a Tirupur export order:
| Stage | Typical Duration | Key Variance Drivers |
|---|---|---|
| Fabric booking confirmation | 1–3 days | Supplier capacity, negotiation |
| Fabric production (greige) | 12–18 days | Mill queue depth, yarn availability |
| Processing (dyeing, finishing) | 8–12 days | Job work queue, water availability (seasonal) |
| Inspection (3rd party or in-house) | 2–4 days | SGS/Intertek slot availability |
| Garment cutting + sewing | 12–18 days | Line balance, style complexity |
| Finishing + packing | 3–5 days | — |
| Customs + shipping | 3–5 days (air), 18–22 days (sea) | Vessel schedule, CFS congestion |
Open data/lead-time-actuals.json for 24 months of stage-by-stage actual vs. planned lead times from a Tirupur combined knitting-dyeing-garmenting facility. The data reveals that processing stage variance (σ = 3.8 days) dominates total order variance — driven primarily by power cuts during Tamil Nadu summer months (April–June) and job work queue congestion during pre-Diwali season.
Monte Carlo Lead Time Simulation
import numpy as np
STAGE_DISTRIBUTIONS = {
"fabric_booking": {"dist": "lognormal", "mu": 1.5, "sigma": 0.4},
"greige_production": {"dist": "normal", "mu": 15, "sigma": 2.5},
"processing": {"dist": "normal", "mu": 10, "sigma": 3.8}, # high variance
"inspection": {"dist": "lognormal", "mu": 1.1, "sigma": 0.3},
"cutting_sewing": {"dist": "normal", "mu": 15, "sigma": 2.2},
"finishing_packing": {"dist": "normal", "mu": 4, "sigma": 0.8},
"customs_shipping_air": {"dist": "normal", "mu": 4, "sigma": 0.7},
}
def simulate_lead_time(n_simulations: int = 10_000,
ship_mode: str = "air",
month: int = 5) -> dict: # month 5 = May (power cut risk)
processing_sigma = 5.5 if month in [4, 5, 6] else 3.8 # seasonal adjustment
total_days = np.zeros(n_simulations)
for stage, params in STAGE_DISTRIBUTIONS.items():
if stage == "customs_shipping_air" and ship_mode == "sea":
mu, sigma = 20, 2.0
elif stage == "processing":
mu, sigma = params["mu"], processing_sigma
else:
mu, sigma = params["mu"], params["sigma"]
if params["dist"] == "lognormal":
total_days += np.random.lognormal(mu, sigma, n_simulations)
else:
total_days += np.random.normal(mu, sigma, n_simulations)
return {
"p50": float(np.percentile(total_days, 50)),
"p80": float(np.percentile(total_days, 80)),
"p95": float(np.percentile(total_days, 95)),
"on_time_probability_38d": float(np.mean(total_days <= 38)),
}A p95 output of 52 days when a buyer's delivery window is 38 days is an immediate escalation trigger — either expedite at air freight premium, push back on delivery date, or shift sourcing to a closer-proximity supplier.
Tirupur Export Logistics Intelligence
Tirupur exports ~₹30,000 crore of knitwear annually, primarily through Chennai and Tuticorin ports (sea freight) and Chennai International Airport (air freight). The Tirupur Exporters' Association (TEA) data shows:
A logistics cost model that compares air vs. sea freight options in real time — incorporating current freight rates (from Freightos or Flexport API), CFS queue depth, and vessel schedules — allows export houses to make ship-mode decisions with full cost visibility rather than defaulting to historical patterns.
Key Takeaways
This is chapter 5 of AI for Textile & Apparel.
Get the full hands-on course — free during early access. Build the complete system. Your projects become your portfolio.
View course details