← Writing

data-science · English · 9 min

🇻🇳 Đọc tiếng Việt

Revenue Forecasting with Data Science: From Classical Statistics to AI

February 2, 2026

From Holt-Winters to XGBoost to Chronos — each revenue forecasting method has its place. This guide helps you pick the right tool for the right problem.

Every December, retailers face the same high-stakes question: how much will we sell next month? Order too little and you lose sales when shelves go empty. Order too much and you lock up capital in unsold inventory. This is not a gut-feel problem — it is a forecasting problem, and data science has well-developed answers.

This guide covers the full stack: what revenue forecasting actually is, what data you need, how each family of methods works, how to evaluate rigorously, and the mistakes that kill a good model before it ever reaches production.


What Revenue Forecasting Is and Why It Matters

Revenue forecasting is the process of estimating future revenue — daily, weekly, monthly, or quarterly — from historical sales data combined with business signals like promotions, seasonality, and market conditions.

Forecast errors carry direct monetary consequences: under-forecasting means stockouts and lost sales; over-forecasting means excess inventory and tied-up capital. Industry estimates suggest a 5% improvement in forecast accuracy in retail can reduce inventory holding costs by 10–15%. For SaaS companies, MRR/ARR forecast accuracy is a board-level KPI.

The problem sits at the intersection of time series analysis, machine learning, and business context. No model is good without domain understanding.


Forecasting Horizons: Short, Medium, Long

Before choosing a method, ask: what decision will this forecast support?

Short-term (1 day – 4 weeks): Daily operations, staffing, flash promotions. Highest accuracy demands, granular data required. Statistical smoothing and ML with recent lag features dominate here.

Medium-term (1–6 months): Supply chain planning, marketing budget, hiring. SARIMA, XGBoost with calendar and lag features, and the Temporal Fusion Transformer are well-suited.

Long-term (6 months – 5 years): Strategic planning, investor forecasts. Directional correctness and scenario ranges matter more than point accuracy. Trend decomposition and regression with macro variables are sufficient.

A three-layer LSTM for a 3-year strategic outlook is over-engineering. A boardroom regression model for a 7-day promotional forecast is under-engineering. Horizon determines method.


The Data You Need

Historical sales data is the foundation, but a good model needs more than that.

Revenue history: At minimum, two full seasonal cycles — at least two years of monthly data for annual seasonality. Daily data works best with 1–3 years.

Calendar features: Day of week, week of year, month, quarter, national holidays. For businesses in Vietnam, this is particularly consequential: Tet (Lunar New Year) is not a single day — it is a multi-week disruption with a buying surge before and a sharp trough after. A feature like days_until_tet (days to the next Lunar New Year) often ranks among the top predictors in ML models for Vietnamese retail.

Promotion data: Discount depth, campaign start and end dates, channel (online/offline). A single promotion can create a revenue spike 2–10x the baseline — larger than any seasonal pattern the model can learn from history alone.

Exogenous variables: GDP, CPI, consumer confidence, exchange rates (important for import-heavy retailers), weather (for F&B and fashion), Google Trends (often leads revenue by 1–4 weeks as a demand signal).

Data quality: Handling missing periods, outliers (the COVID-19 window), and structural breaks (new store opening, product launch) matters as much as model choice.


The Methods: Classical to Modern

1. Moving Average and Exponential Smoothing (ETS / Holt-Winters)

Moving Average (MA) is the simplest starting point: average the last N periods. Adding more weight to recent periods gives Weighted MA. Transparent and easy to implement, but it cannot capture trend or seasonality.

Holt-Winters (ETS — Error-Trend-Seasonal) is the meaningful upgrade. It decomposes a series into level, trend, and seasonal components, each updated continuously through smoothing parameters (alpha, beta, gamma):

  • Additive: Seasonal effect has constant absolute magnitude.
  • Multiplicative: Seasonal effect scales with the baseline level — more common in retail, where holiday spikes are proportionally larger when the underlying revenue is higher.
from statsmodels.tsa.holtwinters import ExponentialSmoothing
 
model = ExponentialSmoothing(
    train,
    trend='add',
    seasonal='mul',
    seasonal_periods=12  # monthly data, annual seasonality
)
fitted = model.fit()
pred = fitted.forecast(3)

ETS is fast, interpretable, and often hard to beat on monthly data with short history. Always build ETS first as a baseline before moving to more complex approaches.

SARIMA — Seasonal ARIMA — adds statistical rigor. The series must be stationary; parameters (p,d,q)(P,D,Q,m) are chosen via ACF/PACF plots or automated with pmdarima.auto_arima. Useful when you need confidence intervals and statistical explainability, but assumes linear relationships and does not scale gracefully with many exogenous variables.

2. Gradient Boosted Trees: XGBoost and LightGBM

This is the dominant approach in production. XGBoost and LightGBM consistently win major forecasting competitions (the M5 Walmart Competition, for example) and are widely deployed in industry for practical reasons: they handle mixed-type features natively, are robust to outliers and missing values, are explainable through SHAP values, and scale to millions of rows across many SKUs and stores.

The key paradigm shift: time series is reframed as a supervised regression problem. Each row is one time step. The target is revenue(t). Features are everything known at prediction time about t.

Feature engineering — the core skill

The model is only as good as its features. The most impactful features for revenue forecasting, roughly ranked by SHAP importance in retail and e-commerce:

Lag features (autoregressive signal):

df['lag_1']   = df['revenue'].shift(1)    # last period
df['lag_7']   = df['revenue'].shift(7)    # same day last week (daily data)
df['lag_28']  = df['revenue'].shift(28)   # same period last month
df['lag_365'] = df['revenue'].shift(365)  # same period last year

Hard rule: only use lags >= the forecast horizon. If you are forecasting 7 days ahead, your smallest lag must be lag_7. Smaller lags are data leakage.

Rolling statistics (smoothed signal):

df['rolling_mean_7']  = df['revenue'].shift(1).rolling(7).mean()
df['rolling_mean_28'] = df['revenue'].shift(1).rolling(28).mean()
df['rolling_std_28']  = df['revenue'].shift(1).rolling(28).std()

Calendar features:

df['day_of_week']    = df['date'].dt.dayofweek
df['month']          = df['date'].dt.month
df['is_weekend']     = (df['date'].dt.dayofweek >= 5).astype(int)
df['is_holiday']     = df['date'].apply(is_national_holiday)
df['days_until_tet'] = df['date'].apply(days_to_next_tet)  # Vietnamese context
df['is_month_end']   = df['date'].dt.is_month_end.astype(int)
df['is_promo']       = ...  # from promotion schedule

Interaction features: is_weekend * is_promo (weekend promotions are multiplicatively stronger), month * is_holiday.

Temporal validation — non-negotiable

from sklearn.model_selection import TimeSeriesSplit
import xgboost as xgb
 
tscv = TimeSeriesSplit(n_splits=5)
for train_idx, val_idx in tscv.split(X):
    X_train, X_val = X.iloc[train_idx], X.iloc[val_idx]
    y_train, y_val = y.iloc[train_idx], y.iloc[val_idx]
 
    model = xgb.XGBRegressor(
        n_estimators=500, learning_rate=0.05,
        max_depth=5, subsample=0.8,
        colsample_bytree=0.8, random_state=42
    )
    model.fit(X_train, y_train,
              eval_set=[(X_val, y_val)],
              early_stopping_rounds=50, verbose=False)

Never shuffle time series data. Temporal cross-validation — expanding window or sliding window — is mandatory.

3. Deep Learning: LSTM and Temporal Fusion Transformer

LSTM (Long Short-Term Memory) is a recurrent network with gating mechanisms that learn long-range sequence dependencies. It works well on large datasets (100K+ rows), complex nonlinear patterns, and multivariate settings. The limitation: LSTM is slow to train, hard to interpret, and regularly outperformed by well-featured XGBoost on tabular data with fewer than 50K rows.

Temporal Fusion Transformer (TFT) — developed by Lim et al. at Google — is a more significant step forward. TFT combines:

  • Variable selection networks: Learns which features are most useful at each time step — interpretability comparable to tree model feature importance.
  • Multi-head attention: Captures long-range dependencies; attention weights show which past steps the model relies on.
  • Quantile outputs: Produces P10/P50/P90 prediction intervals, not just point forecasts — a major advantage for business planning (optimistic vs. pessimistic scenarios).
  • Known future inputs: Accepts planned promotions, calendar events, and holidays as future covariates, something LSTM cannot handle natively.

TFT is particularly well-suited when you have many related series (100+ SKUs), a rich covariate set, a need for prediction intervals, and a dataset of more than 10K rows. It placed at the top of the M5 Walmart Competition across 42K series.

# Using pytorch-forecasting
from pytorch_forecasting import TemporalFusionTransformer, TimeSeriesDataSet

4. Foundation Models: Chronos and TimeGPT

The newest category: pre-trained transformers that forecast zero-shot — without any training on your data.

Amazon Chronos (2024) is fully open-source, runs locally (no API cost, no data privacy concerns), and comes in multiple sizes (small through large). It tokenizes time series values similarly to how an LLM tokenizes text, then autoregressively generates future tokens as future values. On the GIFT-Eval benchmark (2024), Chronos-Large competes with statistical baselines but typically trails a well-tuned XGBoost on dataset-specific tasks.

from chronos import ChronosPipeline
import torch
 
pipeline = ChronosPipeline.from_pretrained(
    "amazon/chronos-t5-small",
    device_map="cpu",
    torch_dtype=torch.float32
)
forecast = pipeline.predict(context, prediction_length=12)

TimeGPT (Nixtla) is a proprietary API with similar capabilities — convenient for rapid prototyping but comes with per-call costs and data privacy considerations when sending sales data off-premises.

When to use foundation models: cold-start scenarios (new product, new store with no history), rapid prototyping, and situations where you lack ML engineering resources. When you have sufficient data and time, XGBoost with good feature engineering still wins on most business-specific tasks.


Method Comparison

MethodSimplicityAccuracyData requirementsInterpretability
Moving Average / ETSVery highModerateLow (≥1 year)Very high
SARIMAModerateModerateMedium (≥2 years)High
XGBoost / LightGBMModerateHighMedium–largeHigh (SHAP)
LSTMLowHighLarge (≥50K rows)Low
Temporal Fusion TransformerLowVery highLarge (many series)Moderate
Chronos / TimeGPTVery highModerateNone (zero-shot)Low

Evaluation Metrics

Choosing the wrong metric is a common failure mode.

MAE (Mean Absolute Error): Average absolute error in revenue units. Easy to explain to non-technical stakeholders.

MAE = mean(|y_true - y_pred|)

RMSE (Root Mean Squared Error): Like MAE but penalizes large errors more heavily. Use when missing a Tet or Black Friday spike is especially costly.

RMSE = sqrt(mean((y_true - y_pred)²))

MAPE (Mean Absolute Percentage Error): Average percentage error — intuitive for business communication ("our forecast is off by 8% on average").

MAPE = mean(|y_true - y_pred| / |y_true|) × 100

Critical MAPE limitation: Undefined or explosive when y_true = 0 or near zero. Asymmetric: penalizes under-forecasting more than over-forecasting. Do not use MAPE when the series contains zero-sales days.

sMAPE addresses this partially: sMAPE = mean(2 × |y_true - y_pred| / (|y_true| + |y_pred|)) × 100

WRMSSE: The M5 Competition metric. Weights errors by each series' revenue share — complex, but accurately reflects business impact when forecasting across many SKUs.

The baseline rule: before reporting any result as "good," compare against the simplest naive baseline: y_hat(t) = y(t − 52 weeks) (same week last year). A model that cannot beat this has no production value in retail.

Reporting to stakeholders: MAE and MAPE. Model selection: RMSE when large errors are costly. Series with zeros: sMAPE.


Common Pitfalls

Data Leakage — the most critical

Data leakage happens when features include information that would not be available at actual prediction time. In time series, this almost always means accidentally including future data.

Common examples:

  • Computing rolling_mean(t-3, t+3) — includes 3 future steps in the rolling window.
  • Using a promotion flag set retroactively after the campaign completed.
  • Random train/test splits instead of temporal splits — the single most common and most damaging mistake in time series.

The fix: always use strictly temporal splits. Every feature must be computed using only data available at time t.

Overfitting to seasonal patterns

A model that memorizes historical seasonality too rigidly will fail when patterns shift — post-COVID shopping behavior, a new competitor, a changed product mix. Signs: low train and validation error but high test error on out-of-distribution periods.

The fix: regularize the feature set, weight recent data more heavily, retrain frequently.

Ignoring structural breaks

A six-week store renovation, a new product cannibalizing an existing one, a competitor opening nearby — these events rupture historical patterns. Flag them as exogenous dummy variables, or train separate models for the pre- and post-break periods.

Reporting only point forecasts

A single point forecast gives stakeholders false confidence about precision. They need to understand the uncertainty range. TFT, CatBoost quantile regression, and conformal prediction wrappers can produce calibrated P10/P50/P90 intervals.

Backtesting on a single split

One train/test split is not sufficient — results depend heavily on which period is held out. Use rolling walk-forward cross-validation with multiple test windows and report mean ± std of error across folds.


What Comes Next

Revenue forecasting is not a problem you solve once. Models need regular retraining (monthly, or when error exceeds a threshold), and production infrastructure should track feature drift and alert when MAPE rises abnormally.

Foundation models like Chronos and TimeGPT are lowering the barrier for cold-start scenarios, but they have not yet displaced XGBoost with good feature engineering on data-rich, business-specific tasks. Probabilistic forecasting — reporting P10/P50/P90 ranges rather than just a point estimate — is becoming the standard in mature data organizations. The question of how foundation models handle Tet seasonality specifically — a multi-week disruption pattern largely absent from Western training data — remains an open empirical question worth watching.

The hardest part of this problem is not model selection. It is building good features, enforcing temporal validation discipline, and having enough domain knowledge to know when a spike is a signal and when it is noise.


Key takeaways:

  • Always build ETS/Holt-Winters first as a mandatory baseline — if a complex model can't beat it, the added complexity isn't justified yet
  • XGBoost with good feature engineering dominates production in most data-rich business forecasting tasks; LSTM and TFT shine when you have many related series and large datasets
  • Temporal splits and walk-forward CV are non-negotiable — random splits with time series data are data leakage, no exceptions
  • Lag features must be >= the forecast horizon; calendar features should reflect local holidays and patterns that drive your specific business
  • Foundation models (Chronos, TimeGPT) are ideal for cold-start scenarios; once you have sufficient history, well-featured XGBoost typically still wins on business-specific tasks
data-scienceforecastingmachine-learningtime-seriesbasics

Sources

  1. Forecasting: Principles and Practice (3rd ed.) — Hyndman & Athanasopoulos
  2. Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting — Lim et al., 2019
  3. Chronos: Learning the Language of Time Series — Ansari et al., Amazon Research, 2024
  4. XGBoost: A Scalable Tree Boosting System — Chen & Guestrin, 2016