Skip to main content

Hybrid time series forecasting library combining Prophet with gradient boosting models

Project description

HybridTS

HybridTS Logo

Hybrid Time Series Forecasting for Python

Combines Prophet's trend and seasonality detection with gradient boosting (XGBoost / LightGBM) to correct residuals — delivering more accurate forecasts than either model alone.

Python Version License Version Tests


How It Works

  1. Prophet fits trend, seasonality, and holiday effects
  2. XGBoost / LightGBM learns from the residuals using engineered features
  3. Final forecast = Prophet baseline + ML residual correction

Installation

pip install hybridts

Quick Start

from hybridts import HybridForecaster, ProphetModel, XGBoostTuner
import pandas as pd

prophet = ProphetModel()
xgb = XGBoostTuner()

forecaster = HybridForecaster(primary_model=prophet, secondary_model=xgb)

df = pd.read_csv("data.csv", parse_dates=["ds"])  # columns: ds, y
forecaster.fit(df)
forecast = forecaster.predict(horizon=30)
print(forecast)

Data Format

A pandas DataFrame with exactly two columns:

Column Type Description
ds datetime Date of observation
y float Value to forecast

Core API

HybridForecaster

HybridForecaster(
    primary_model,           # ProphetModel instance
    secondary_model,         # XGBoostTuner or LightGBMTuner instance
    test_size=30,            # holdout size for evaluate()
    paydays_set=None,        # set of payday Timestamps (auto-generated if None)
    holidays_country="BR",   # country code for auto-generated holidays
    holidays_state=None,     # state/subdivision code
)

fit(df, holidays=<auto>, features=<auto>)

Trains both models. By default, holidays and features are auto-generated from the data.

forecaster.fit(df)                        # auto holidays + auto features
forecaster.fit(df, holidays=None)         # no holidays passed to Prophet
forecaster.fit(df, holidays=my_holidays)  # custom holidays DataFrame
forecaster.fit(df, features=None)         # secondary model trains without exogenous features

predict(horizon, features=<auto>)

Returns a DataFrame with horizon rows:

Column Description
data Forecast date
forecast_primary_base Prophet baseline
residual_correction ML adjustment
forecast_final Final hybrid forecast

evaluate(df, test_size=None)

Evaluates on a holdout set without data leakage. Returns (metrics, y_true, y_pred).

metrics, y_true, y_pred = forecaster.evaluate(df)

# Access full metrics reports after evaluate()
forecaster.metrics_report_          # ForecastMetrics for the hybrid forecast
forecaster.primary_metrics_report_  # ForecastMetrics for the primary model alone

evaluate_and_fit(df, test_size=None)

Evaluates on holdout, then retrains on the full dataset.

forecaster, metrics = forecaster.evaluate_and_fit(df)

Models

ProphetModel

Wraps Prophet with automated hyperparameter tuning via cross-validation.

ProphetModel(
    param_grid={"changepoint_prior_scale": [0.05, 0.1], ...},  # grid search params
    cv_params={"initial": "300 days", "period": "30 days", "horizon": "30 days"},
    yearly_seasonality=True,
    weekly_seasonality=True,
    daily_seasonality=False,
    static_params={...},   # used by fit_static() — skips CV
)
Method Description
fit(df, holidays) Tunes hyperparameters via CV, then fits on full data
fit_static(df, holidays) Fits with static_params, no CV
predict(df) Returns Prophet forecast DataFrame

XGBoostTuner

Wraps XGBoost via sktime's make_reduction with grid search and expanding window CV.

XGBoostTuner(
    test_size=30,
    param_grid={"window_length": [21], "estimator__max_depth": [5, 7], ...},
    static_params={"n_estimators": 200, "max_depth": 5, ...},
    cv_initial_window=270,
    cv_step_length=30,
    window_length=21,
    fh=30,
    strategy="recursive",
    regressor_params={"random_state": 42},
)

LightGBMTuner

Same interface as XGBoostTuner, using LightGBM as the estimator.

LightGBMTuner(
    lgbm_regressor_params={"strategy": "recursive", "n_estimators": 200, ...},
    test_size=30,
    initial_window=270,
    step_length=30,
    window_length=21,
    param_grid={"window_length": [21, 28], ...},
)

Both models expose fit(), fit_static(), and predict().


Feature Engineering

from hybridts import create_features, get_brazilian_paydays, create_holidays_prophet

# Generate Brazilian payday dates
paydays = get_brazilian_paydays(start_year=2022, end_year=2025)

# Create exogenous features
features = create_features(
    df_dates=df[["ds"]],
    paydays_set=paydays,       # optional — all payday features zeroed if None
    min_year=2022,
    max_year=2025,
    holidays_country="BR",
    holidays_state="SP",
)

Generated features:

Feature Description
is_weekend 1 if Saturday or Sunday
is_month_start 1 if day <= 9
is_month_end 1 if last day of month
day_of_week 0 (Mon) to 6 (Sun)
day_of_month 1-31
is_payday 1 if date is a payday
is_adiantamento 1 if salary advance day
sextou_com_dinheiro 1 if Friday and payday
dias_desde_pagamento Days since last payday
is_holiday 1 if public holiday
is_holiday_eve 1 if day before holiday
is_post_holiday 1 if day after holiday

Metrics

After evaluate(), two ForecastMetrics reports are available on the forecaster instance.

from hybridts.src.metrics import ForecastMetrics

report = forecaster.metrics_report_

report.mae        # Mean Absolute Error
report.mse        # Mean Squared Error
report.rmse       # Root Mean Squared Error
report.mape       # Mean Absolute Percentage Error (%)
report.smape      # Symmetric MAPE (%)
report.r_squared  # Coefficient of determination
report.bias       # Mean signed error (+ = underestimation, - = overestimation)

print(report.summary())
# Forecast Metrics Summary:
# MAE: 142.3401
# MSE: 32401.2000
# ...

report.all_metrics()  # returns a dict with all metrics

ForecastMetrics can also be used standalone on any y_true / y_pred pair:

report = ForecastMetrics(y_true, y_pred)
print(report.summary())

Logging

HybridTS uses loguru with logging disabled by default (library-safe). To enable:

from loguru import logger
logger.enable("hybridts")

Project Structure

hybridts/
├── __init__.py                  # public API
└── src/
    ├── features/
    │   ├── data_processor.py    # TimeSeriesProcessor
    │   ├── engineering.py       # create_features
    │   └── holidays.py          # create_holidays_prophet, get_brazilian_paydays
    ├── models/
    │   ├── primary/
    │   │   └── prophet.py       # ProphetModel
    │   └── secondary/
    │       ├── xgboost.py       # XGBoostTuner
    │       └── lightgbm.py      # LightGBMTuner
    ├── metrics/
    │   └── forecast.py          # ForecastMetrics
    ├── pipeline/
    │   └── pipeline.py          # HybridForecaster
    └── exception/
        ├── model_exception.py   # ModelTrainingException, ModelPredictionException
        └── dataframe_exception.py

License

MIT — see LICENSE


Davi FrancoGitHub

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hybridts-0.3.0.tar.gz (43.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hybridts-0.3.0-py3-none-any.whl (22.5 kB view details)

Uploaded Python 3

File details

Details for the file hybridts-0.3.0.tar.gz.

File metadata

  • Download URL: hybridts-0.3.0.tar.gz
  • Upload date:
  • Size: 43.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for hybridts-0.3.0.tar.gz
Algorithm Hash digest
SHA256 7eb08efc686d322760b7080abb6c0a40dceb57c9e0d08953a644113063c9f479
MD5 66b06bef82853865ceec8074f9484d20
BLAKE2b-256 5a7b36a531294c7ded9974a91f474e70a9b2b3548c39a799efd1d4452257b81e

See more details on using hashes here.

File details

Details for the file hybridts-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: hybridts-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 22.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for hybridts-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cedbb3664bcfad767567327e72bc659e6a01af25c58a5c2b03fbca915bc03a1e
MD5 69257aa8f25565e7c8eccf7f3c5f8056
BLAKE2b-256 8a5db01d260561c5d6fd890a217a42430bf1b81693ef1c4dded997b15830c882

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page