A time-series research project on next-day West Texas Intermediate (WTI) crude-oil returns. It compares probabilistic LSTMs with XGBoost, AR, naive, and GARCH benchmarks, then tests whether the LSTM uncertainty estimates are actually calibrated.
Do heteroscedastic LSTMs produce statistically calibrated uncertainty estimates for next-day WTI returns, and do they improve on a classical GARCH(1,1) benchmark?
The target is the next-day log return
r(t+1) = log(P(t+1)) - log(P(t))
The modelling panel covers 31 January 2017 to 3 March 2026. Evaluation uses a chronological split to prevent look-ahead leakage:
| Split | Period | Observations in the calibration study |
|---|---|---|
| Train | through 30 December 2022 | 1,235 |
| Validation | 3 January 2023 – 28 June 2024 | 312 |
| Test | 1 July 2024 – 3 March 2026 | 348 |
- After correcting publication timing and fold-level preprocessing, the pure-NLL LSTM achieves test RMSE 0.022982 and 54.60% directional accuracy.
- The RMSE improvement over predicting zero return is only 0.000029 and is not statistically significant (
p = 0.622); the directional result is also not significant at 5% (p = 0.096). - The composite LSTM is better calibrated under the reported Gaussian tests, but its RMSE, MAE, directional accuracy, and log score are all worse.
- GARCH is statistically indistinguishable from pure NLL on Gaussian log score (
p = 0.937) and has the best post-hoc Student-t NLL. - Every volatility-scaled strategy has negative pre-cost return and Sharpe ratio. The corrected result is weak/null evidence, not a profitable trading signal.
| Model | RMSE | Direction | Gaussian NLL | Student-t NLL |
|---|---|---|---|---|
| Pure-NLL LSTM | 0.022982 | 54.60% | -2.3159 | -2.3413 |
| Composite LSTM | 0.025895 | 49.43% | -2.2277 | -2.2343 |
| GARCH(1,1) | — | — | -2.3129 | -2.3661 |
| Zero-return mean forecast | 0.023011 | 50.00% | — | — |
The leakage-corrected report contains the complete methodology, diagnostics, limitations, and improvement routes. The original published report remains available as a historical pre-correction baseline; its status and commit are recorded in the baseline note.
.
├── data/
│ └── README.md # expected inputs and generated datasets
├── docs/assets/
│ └── calibration_curve.png # README figure
├── notebooks/daily/
│ ├── data_processing.ipynb # refresh market prices and build base data
│ ├── data_analysis.ipynb # exploratory analysis
│ ├── feature_engineering.ipynb # core, full, and PCA feature sets
│ └── return_prediction/
│ ├── lstm_model.ipynb # model training and comparison
│ └── probabilistic_calibration_study.ipynb
├── report/
│ ├── corrected/ # corrected report and regenerated figures
│ ├── figures/ # historical pre-correction figures
│ ├── individual_report.pdf # historical pre-correction report
│ ├── individual_report.tex
│ └── references.bib
├── scripts/
│ └── grid_search_nll.py # resumable XGBoost/LSTM grid search
├── tests/
│ ├── test_repository.py # structural and notebook checks
│ └── test_temporal_preprocessing.py # temporal leakage regressions
├── wti_return_forecasting/
│ └── temporal.py # availability-safe transformations
└── requirements.txt
The research combines market prices, EIA inventory measures, Federal Reserve text features, and GDELT sentiment aggregates for 12 oil-relevant countries. The consolidated datasets are not redistributed in this portfolio repository because they contain third-party-derived inputs. See data/README.md for the expected filenames, schemas, and generated artifacts.
Notebook outputs and the final report are retained so the analysis can be reviewed without the private working data.
-
Clone the repository and create an environment:
git clone https://github.com/PeterLP123/wti-return-forecasting.git cd wti-return-forecasting python -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip pip install -r requirements.txt
-
Place the private source datasets in the locations documented in data/README.md.
-
Build the feature datasets, explore them, and run the main modelling notebook:
jupyter lab
data_processing.ipynbfeature_engineering.ipynbdata_analysis.ipynbreturn_prediction/lstm_model.ipynb
-
Generate the canonical NLL and composite-model artifacts consumed by the calibration study. From the repository root, run:
WTI_SEARCH_PROFILE=corrected \ WTI_RUN_ID=corrected_leakage_safe_v1 \ python scripts/grid_search_nll.py
This bounded profile writes resumable checkpoints, metrics, and a provenance manifest to
results/corrected_leakage_safe_v1/. SetWTI_SEARCH_PROFILE=exhaustiveonly for the full research grid. -
Run
return_prediction/probabilistic_calibration_study.ipynbto reproduce the formal calibration diagnostics and corrected report figures. If the optionalllvmliteaccelerator is unavailable, prefix the command withARCH_DISABLE_NUMBA=1to usearch's supported pure-Python fallback.
The availability and preprocessing contract is documented in docs/FEATURE_AVAILABILITY.md. EIA events are mapped to release dates, daily GDELT/Fed features receive a conservative one-row lag, and imputation, PCA, scaling, and feature selection are fitted independently inside each chronological validation fold.
Repository checks validate Python syntax, notebook JSON, recorded notebook errors, both reports, common submission debris, publication-date rules, conservative daily lags, and fold-local PCA/scaling:
pip install -r requirements-dev.txt
pytest -qThe corrected report can be rebuilt independently with:
cd report/corrected
latexmk -pdf -interaction=nonstopmode -halt-on-error individual_report_corrected.texThis is an academic research project, not investment advice or a production trading system. The reported backtests and calibration diagnostics are historical and do not establish future profitability.
