A machine learning and deep learning pipeline for forecasting non-ferrous metals prices (Aluminium, Copper, Zinc) across multiple forecasting horizons. The system implements both univariate and multivariate approaches, combining lagged feature engineering with correlation-based feature selection, bootstrap uncertainty quantification, and confidence interval estimation — enabling manufacturing firms to make data-driven hedging and procurement decisions.
- Motivation
- Architecture
- Methodology
- Key Findings
- Setup
- Usage
- Pipeline Output
- Configuration
- Project Structure
- Data Privacy Notice
- Tech Stack
Raw materials prices have historically been highly volatile. The main drivers behind this volatility include global economic conditions, electricity prices, growth of developing countries, weather conditions, currency exchange rates, interest rates, and unpredictable phenomena such as pandemics and wars. Non-ferrous metals — aluminium, copper, and zinc — are particularly affected.
This volatility constitutes a serious challenge for manufacturers, since raw material costs represent a major share of total production costs. Unstable costs translate into unstable profit margins, decreasing operating capital, and potentially threatening firm survival. Accurate price forecasting enables effective hedging strategies, procurement optimization, and risk-informed pricing decisions.
This project compares 7 machine learning methods and 1 deep learning method across 7 forecasting horizons (1–6 and 12 months), in both univariate and multivariate configurations, to determine the optimal approach for non-ferrous metals price prediction.
┌─────────────────────┐
│ Data Loading │
│ (Excel/CSV) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Temporal │
│ Resampling │
│ (Monthly) │
└──────────┬──────────┘
│
┌────────────────┼────────────────┐
│ │
┌─────────▼──────────┐ ┌───────────▼──────────┐
│ Lagged Feature │ │ LSTM Sequence │
│ Generation │ │ Builder │
│ (1–90 lags) │ │ (L=50 lookback) │
└─────────┬──────────┘ └───────────┬──────────┘
│ │
┌─────────▼──────────┐ │
│ Correlation- │ │
│ Based Feature │ │
│ Selection │ │
└─────────┬──────────┘ │
│ │
┌─────────▼──────────┐ │
│ Lead Time │ │
│ Filtering │ │
│ (anti look-ahead)│ │
└─────────┬──────────┘ │
│ │
┌─────────▼──────────┐ ┌───────────▼──────────┐
│ StandardScaler │ │ Max-Value │
│ Normalization │ │ Normalization │
└─────────┬──────────┘ └───────────┬──────────┘
│ │
┌─────────▼──────────┐ ┌───────────▼──────────┐
│ ML Models (×7) │ │ LSTM Network │
│ + Bootstrap │ │ (5 units) │
│ (1000 iters) │ │ │
└─────────┬──────────┘ └───────────┬──────────┘
│ │
└────────────────┬────────────────┘
│
┌──────────▼──────────┐
│ 6-Metric │
│ Evaluation Suite │
└──────────┬──────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌─────────▼──────┐ ┌──────▼───────┐ ┌──────▼───────┐
│ Forecast │ │ Model │ │ Correlation│
│ Plots + CI │ │ Comparison │ │ Analysis │
└────────────────┘ └──────────────┘ └──────────────┘
Loader (src/data/loader.py):
- Ingests commodity price data from Excel files with datetime indexing
- Validates date ranges and column availability
Resampler (src/data/resampler.py):
- Converts daily/weekly data to monthly resolution via mean aggregation
- Supports configurable resampling frequencies (daily, weekly, monthly, yearly)
Splitter (src/data/splitter.py):
- Temporal train/test split preserving chronological order (default: 90/10)
- Prevents data leakage by ensuring all test data occurs after training data
Lagged Feature Generation (src/features/lag_generator.py):
- Creates time-lagged versions of each variable from lag 1 to lag 90
- Univariate mode: lags only of the target commodity
- Multivariate mode: lags of all commodities and exogenous variables (exchange rates, energy prices, economic indicators)
Correlation-Based Feature Selection (src/features/correlation_selector.py):
- Computes Pearson correlation between each lagged feature and the target
- Univariate threshold: |r| ≥ 0.4 (stricter, fewer features)
- Multivariate threshold: |r| ≥ 0.01 (relaxed, captures cross-commodity relationships)
- Exports sorted correlation rankings for interpretability
Lead Time Filtering (src/features/lead_time_filter.py):
- Removes lagged features where lag < forecasting horizon
- Prevents look-ahead bias: ensures no future information leaks into the model
- Automatically adjusts feature set per lead time
Scaling (src/features/scaler.py):
- StandardScaler fit on training data only, applied to test data
- Prevents information leakage from test set statistics
Sequence Builder (src/features/sequence_builder.py):
- Constructs sliding-window sequences for LSTM input
- Configurable lookback window (default: 50 timesteps)
- Max-value normalization per feature channel
Seven ML models and one deep learning architecture are benchmarked:
| Model | Type | Strengths |
|---|---|---|
| XGBoost | Gradient Boosting | Handles non-linearities, feature interactions, regularization |
| Random Forest | Ensemble | Robust to outliers, implicit feature importance |
| KNN | Instance-Based | Captures local patterns, no training phase |
| MLP | Neural Network | Universal approximator, captures complex mappings |
| SVR | Kernel Method | Effective in high-dimensional spaces |
| Linear Regression | Linear Baseline | Interpretable, fast, establishes lower bound |
| Ridge | Regularized Linear | L2 regularization prevents overfitting |
| LSTM | Recurrent Neural Network | Captures long-term temporal dependencies |
Bootstrap Aggregation (src/models/bootstrap.py):
- 1000 bootstrap iterations with replacement
- Each iteration trains a fresh model on a resampled training set
- Generates prediction distribution over the test set
- Confidence intervals computed as quantiles:
- Lower bound: 2.5th percentile (for 95% CI)
- Central prediction: 50th percentile (median)
- Upper bound: 97.5th percentile
This approach provides probabilistic forecasts rather than point estimates — critical for risk management applications where decision-makers need to understand prediction uncertainty.
Six complementary metrics assess different aspects of forecast quality:
| Metric | What it Measures |
|---|---|
| RMSE | Root Mean Squared Error — penalizes large deviations |
| MAE | Mean Absolute Error — average deviation in USD |
| MAPE | Mean Absolute Percentage Error — scale-independent accuracy |
| R² | Coefficient of Determination — variance explained |
| NSE | Nash-Sutcliffe Efficiency — benchmark vs. mean prediction |
| EMSE | Expected Mean Squared Error — average squared deviation |
- Forecast plots with confidence intervals — actual vs. predicted with shaded CI bands
- Model comparison bar charts — side-by-side metric comparison across lead times
- Correlation heatmaps — top correlated features ranked by absolute Pearson r
The multivariate Extreme Gradient Boosting (XGBoost) consistently outperforms all other models for aluminium, copper, and zinc price forecasting across all tested lead times. The multivariate approach, which incorporates cross-commodity dependencies and macroeconomic indicators, yields superior accuracy compared to univariate models that rely solely on the target commodity's own price history.
- Python 3.10+
- pip
git clone https://github.com/Pargo18/Commodities-price-forecasting.git
cd Commodities-price-forecasting
pip install -r requirements.txtpython run.py --mode univariatepython run.py --mode multivariate --commodity Aluminiumpython run.py --lead-times 1 3 6 12python run.py --skip-viz --output-dir results/experiment_01jupyter notebook "exploratory analysis/Exploratory analysis - monthly resolution.ipynb"results/
├── model_results.xlsx # All models × commodities × lead times
├── results_Aluminium.xlsx # Per-commodity results
├── results_Copper.xlsx
├── results_Zinc.xlsx
├── comparison_Aluminium.png # RMSE comparison bar chart
├── comparison_Copper.png
├── comparison_Zinc.png
└── forecast_[commodity]_[model]_lt[N].png # Forecast plots with CI
All hyperparameters are centralized in src/config.py:
| Config Section | Key Parameters |
|---|---|
DataConfig |
Input path, resampling frequency, commodity list |
FeatureConfig |
Lag range (1–90), correlation thresholds, lead times |
ModelConfig |
Test ratio (10%), bootstrap iterations (1000), confidence (95%), model hyperparameters |
LSTMConfig |
Sequence length (50), LSTM units (5), learning rate, epochs |
Commodities-price-forecasting/
├── run.py # CLI entry point
├── requirements.txt
├── README.md
├── assets/
│ └── thumbnail.png
├── exploratory analysis/ # EDA notebooks (multiple resolutions)
│ ├── Exploratory analysis - daily resolution.ipynb
│ ├── Exploratory analysis - weekly resolution.ipynb
│ ├── Exploratory analysis - monthly resolution.ipynb
│ └── Exploratory analysis - yearly resolution.ipynb
├── modeling/ # Original modeling notebooks
│ ├── Univariate Modeling - monthly resolution.ipynb
│ ├── Multivariate Modeling - monthly resolution.ipynb
│ ├── LSTM Univariate+Multivariate Modeling - monthly resolution.ipynb
│ └── Modeling - daily resolution.ipynb
├── results/ # Model outputs and performance plots
└── src/
├── config.py # Centralized configuration
├── data/
│ ├── loader.py # Data ingestion
│ ├── resampler.py # Temporal resampling
│ └── splitter.py # Chronological train/test split
├── features/
│ ├── lag_generator.py # Lagged feature creation (1–90)
│ ├── correlation_selector.py # Pearson correlation feature selection
│ ├── lead_time_filter.py # Anti-look-ahead bias filtering
│ ├── scaler.py # StandardScaler normalization
│ └── sequence_builder.py # LSTM sequence construction
├── models/
│ ├── ml_models.py # 7 ML model factory
│ ├── lstm_model.py # LSTM architecture builder
│ ├── bootstrap.py # Bootstrap uncertainty quantification
│ └── trainer.py # Training orchestrator
├── evaluation/
│ ├── metrics.py # 6-metric evaluation suite
│ └── comparison.py # Cross-model result compilation
├── visualization/
│ ├── forecast_plot.py # Time series forecast + CI plots
│ ├── model_comparison.py # Grouped bar chart comparison
│ └── correlation_heatmap.py # Feature correlation ranking
└── utils/
└── logger.py # Logging configuration
Total: 20 Python modules across 6 subpackages + 8 Jupyter notebooks
This repository does not contain commodity price data. The pipeline is designed to work with Excel files placed in the
data/directory. Raw data is excluded from this repository for licensing and compliance reasons. The modular architecture accepts any time-series dataset with commodity price columns and a datetime index.
| Category | Libraries |
|---|---|
| Machine Learning | scikit-learn, XGBoost |
| Deep Learning | TensorFlow / Keras (LSTM) |
| Data Processing | Pandas, NumPy |
| Visualization | Matplotlib |
| Statistical Analysis | Pearson correlation, bootstrap resampling |
| Core | Python 3.10+ |