Library / SDK
skforecast/skforecast avatar
skforecast/skforecast

skforecast: wrapping scikit-learn estimators into recursive and multi-step forecasters

Python library for time series forecasting using scikit-learn compatible models, statistical methods, and foundation models

1,534 stars199 forksPythonBSD-3-Clause

At a glance

What is it?
skforecast puts a forecasting scaffold around any scikit-learn compatible estimator, so LightGBM or XGBoost can drive multi-step predictions with lags, backtesting and prediction intervals. The value is the plumbing, and the cost is that you inherit the estimator's weaknesses along with its API.
Who is it for?
Adopt skforecast if your team already writes scikit-learn pipelines and wants gradient boosting on lagged features without hand-rolling the recursion, the backtest loop and the interval logic. Do not adopt it if you need a single model that learns cross-series structure natively, or if you cannot afford to retrain the wrapped estimator on every refit cycle.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap skforecast fills between scikit-learn and forecasting

scikit-learn estimators assume rows are independent and identically distributed. A time series is neither. If you hand a gradient boosting regressor a column of raw values and ask it to predict tomorrow, it has no way to know that yesterday matters more than last year, and it has no concept of a forecast horizon. The usual workaround is to build lag features by hand, fit the model, then feed predictions back in as inputs to produce step two. That feedback loop is where most homegrown implementations go wrong, because the training matrix and the inference path drift apart.

skforecast targets that gap. The README describes it as a Python library for time series forecasting using scikit-learn compatible models, statistical methods and foundation models, and states that it works with any estimator compatible with the scikit-learn API, naming LightGBM, XGBoost, CatBoost and Keras among the options. The audience is therefore specific: engineers who already trust a scikit-learn estimator on tabular data and want to point it at a series without writing the forecasting scaffold themselves. It is not aimed at someone who wants a turnkey statistical model with no feature engineering, and it is not a replacement for a dedicated deep learning forecasting framework.

How ForecasterRecursive turns a regressor into a forecasting loop

The core mechanism is visible in the quick example. You construct ForecasterRecursive with two arguments, an estimator and a lags value, then call fit(y=y) and predict(steps=12). The lags parameter is what makes the estimator usable: the wrapper builds a supervised learning problem where the target is shifted by each lag, so the model sees the last 15 observations as features when predicting the next value. The estimator itself is untouched. It is still a LGBMRegressor, trained through the standard fit interface.

The recursive part is the multi-step behaviour. To produce twelve future values, the wrapper predicts one step, appends that prediction to the available history, rebuilds the lag features, and predicts again. That is why the class is named ForecasterRecursive rather than something neutral. The README's example output shows a pandas Series indexed from 2008-07-01 with monthly frequency and the name pred, which tells you the wrapper preserves the datetime index and frequency of the input rather than returning a bare array. The topics list on the repository also references multi-step forecasting, backtesting forecasters, prediction intervals, probabilistic forecasting, exogenous predictors and multi-series forecasting, so the recursive loop is one entry point among several rather than the whole library.

Installation, dependencies and the first working fit

The README documents installation through PyPI and conda-forge, and the badge row lists Python 3.10 through 3.14. The conda channel is conda-forge, so the package name is skforecast on both. The quick example imports from three places: skforecast.recursive for ForecasterRecursive, skforecast.datasets for load_demo_dataset, and lightgbm for the estimator. That import layout matters when you are reading older tutorials, because the module path under skforecast has changed across the 0.22, 0.23 and 0.24 releases listed in the repository metadata.

The minimal working sequence from the README is to load the demo series, instantiate the forecaster with an estimator and a lag count, fit on the series, and call predict with a step count. Note that fit takes the series as a keyword argument named y rather than positionally, and that predict takes steps as a keyword. If you are wiring this into an existing pipeline, the estimator is where you pass random_state and any verbosity settings, since the wrapper does not abstract those away. The README also points to a Skforecast Studio application that generates Python code visually, and to skforecast-ai, an assistant that pairs a deterministic engine powered by skforecast with an LLM reasoning layer. Treat generated code from either as a starting point that still needs the estimator and lag choices checked against your own series.

Backtesting and prediction intervals are the parts worth paying for

Anyone can write a lag matrix. The harder engineering is honest evaluation and uncertainty. The repository topics include backtesting-forecasters, prediction-intervals and probabilistic-forecasting, which indicates these are first-class concerns rather than afterthoughts. A backtesting forecaster exists to answer a question that a single train-test split cannot: how the model performs when it is refit on a rolling origin and asked to predict forward from each cut point. That is the evaluation that matters for a recursive model, because recursive error compounds and a single split will hide it.

Prediction intervals matter for the same reason. A point forecast from a recursive loop carries no native uncertainty estimate, so the library has to supply one. The README does not spell out the interval method in the material available here, so I will not guess at it. What can be said is that the topics list groups prediction intervals with probabilistic forecasting, which suggests interval output is a supported feature rather than something you bolt on. If interval calibration is central to your use case, that is a specific thing to verify in the documentation before adopting, because the quality of an interval method is not something a feature list establishes.

Where the recursive wrapper becomes the wrong tool

The recursive strategy has a structural weakness that no amount of wrapper code removes. Every prediction after the first is conditioned on predictions the model made itself, not on observed data. If the one-step model is biased, that bias is fed back as an input and can compound across the horizon. For a twelve-step monthly forecast the effect may be tolerable. For a long horizon on a series with strong trend or regime shifts, it can dominate. The library's multi-step forecasting topic suggests alternative strategies exist, but the default example is recursive and that is the path most users will take.

There is a second cost: the wrapped estimator must be refit whenever you want the model to incorporate new observations. A statistical model like ARIMA can be updated with new data more cheaply than retraining a gradient boosting model from scratch. If your series updates hourly and your refit budget is tight, the scikit-learn estimator you chose for accuracy becomes the bottleneck. A third limitation is that the estimator has no inherent notion of seasonality or trend decomposition. Whatever structure the model learns, it learns from the lag features you configured. Set lags to 15 on monthly data and you have given the model no direct way to see the same month last year, which is a common and avoidable mistake.

How it differs from a statistical or deep learning forecasting stack

The closest comparison is a statistical modelling library where the model and the forecasting logic are the same object. With an ARIMA or SARIMAX implementation, the recursion, the seasonality and the uncertainty are properties of the fitted model, not of a wrapper around a separate estimator. The trade-off is direct: you get a model whose assumptions are explicit and whose intervals come from the fitted likelihood, but you give up the ability to swap in gradient boosting or a neural network without rewriting your forecasting code. skforecast inverts that. The forecasting logic is fixed and reusable, the model is a parameter.

Against a deep learning forecasting framework, the difference is the feature contract. skforecast expects you to specify lags and, per the topics list, exogenous predictors, so the model's inputs are explicit and inspectable. A sequence model learns its own internal representation of history and typically needs more data and more tuning to get there. For a few hundred observations and a handful of exogenous variables, the explicit lag approach is easier to debug. For thousands of related series where cross-series information should be shared, a model designed for that setting is a better fit, and skforecast's multi-series support is a wrapper-level concern rather than a change to how the underlying estimator learns.

Licence, release cadence and what to check before you pin a version

The repository is licensed BSD-3-Clause, which permits commercial use and modification provided the copyright notice and disclaimer are retained. It is a permissive licence with no copyleft obligation on your own code, and it is the same family of licence used by scikit-learn itself, which keeps the dependency story simple. This is not legal advice; if you are redistributing the library inside a product, have your own counsel read the LICENSE file rather than a review.

The release history shows v0.22.0 in April 2026, v0.23.0 in July 2026 and v0.24.0 in August 2026, with the last push to main in September 2026. Three minor releases in five months means the API is still moving, and the module paths in the quick example are the kind of thing that shifts between minor versions. Pin the version in your requirements file and read the release notes before upgrading, particularly if you depend on the backtesting or interval interfaces. The README also advertises an llms.txt file at skforecast.org, which is a reasonable way to get an assistant to read current documentation instead of a stale tutorial. The project is listed as affiliated with NumFOCUS and GC.OS, and the README includes a citation block with a Zenodo DOI for academic use.

Editorial conclusion

Adopt skforecast if your team already writes scikit-learn pipelines and wants gradient boosting on lagged features without hand-rolling the recursion, the backtest loop and the interval logic. Do not adopt it if you need a single model that learns cross-series structure natively, or if you cannot afford to retrain the wrapped estimator on every refit cycle. Before committing, verify the fit and predict contract for your chosen estimator against the examples in the documentation, and confirm the version pin you install matches the API in the tutorial you are copying from.

Official sources

  1. License: BSD-3-Clause
  2. Project website
  3. README
  4. Releases
  5. skforecast/skforecast on GitHub
Community notes

Community notes