Claude Code for Prophet: Time Series Forecasting — Claude Skills 360 Blog
Blog / AI / Claude Code for Prophet: Time Series Forecasting
AI

Claude Code for Prophet: Time Series Forecasting

Published: November 5, 2027
Read time: 5 min read
By: Claude Skills 360

Prophet forecasts time series with trend, seasonality, and holiday effects. pip install prophet. from prophet import Prophet. Data format: df = pd.DataFrame({"ds": dates, "y": values}) — ds must be datetime. Fit: model = Prophet(), model.fit(df). Forecast: future = model.make_future_dataframe(periods=365), forecast = model.predict(future) — returns yhat yhat_lower yhat_upper. Plot: model.plot(forecast), model.plot_components(forecast). Seasonality mode: Prophet(seasonality_mode="multiplicative") for percentage trends. Holidays: model.add_country_holidays(country_name="US"). Custom seasonal: model.add_seasonality(name="monthly", period=30.5, fourier_order=5). External regressors: model.add_regressor("temperature") — column must be in both train and future df. Tuning: key params are changepoint_prior_scale (0.001-0.5, default 0.05 — higher = more flexible trend), seasonality_prior_scale (0.01-10, default 10), holidays_prior_scale. Changepoints: Prophet(changepoint_range=0.8, n_changepoints=25). Uncertainty: Prophet(uncertainty_samples=1000). Cross-validation: from prophet.diagnostics import cross_validation, performance_metrics, df_cv = cross_validation(model, initial="730 days", period="180 days", horizon="365 days"), df_p = performance_metrics(df_cv). Logistic growth: Prophet(growth="logistic") with cap and floor columns. Claude Code generates Prophet forecasting pipelines, hyperparameter tuners, cross-validation scripts, and multi-series batch forecasters.

CLAUDE.md for Prophet

## Prophet Stack
- Version: prophet >= 1.1
- Data: pd.DataFrame({"ds": datetime_series, "y": float_series})
- Fit: Prophet(**params).fit(df)
- Forecast: model.make_future_dataframe(periods=N) → model.predict(future)
- Key params: changepoint_prior_scale (0.05) | seasonality_prior_scale (10)
- Holidays: model.add_country_holidays("US") | custom holiday DataFrame
- Custom seasonality: add_seasonality(name, period, fourier_order)
- Regressors: add_regressor("col") — must exist in both train and future df
- Cross-val: cross_validation(model, initial, period, horizon) → performance_metrics

Prophet Forecasting Pipeline

# ml/prophet_pipeline.py — time series forecasting with Meta Prophet
from __future__ import annotations
import warnings
import itertools
import numpy as np
import pandas as pd
from pathlib import Path

warnings.filterwarnings("ignore")

from prophet import Prophet
from prophet.diagnostics import cross_validation, performance_metrics
from prophet.plot import add_changepoints_to_plot


# ── 1. Data helpers ───────────────────────────────────────────────────────────

def make_prophet_df(
    dates:  pd.DatetimeIndex | list,
    values: np.ndarray | list,
    cap:    float = None,
    floor:  float = None,
) -> pd.DataFrame:
    """
    Create a Prophet-compatible DataFrame.
    cap/floor are required for logistic growth models.
    """
    df = pd.DataFrame({"ds": pd.to_datetime(dates), "y": values})
    if cap is not None:
        df["cap"]   = cap
    if floor is not None:
        df["floor"] = floor
    return df


def resample_series(
    df:     pd.DataFrame,
    freq:   str = "D",    # "H" hourly, "D" daily, "W" weekly, "M" monthly
    agg:    str = "sum",  # "sum" | "mean" | "last"
) -> pd.DataFrame:
    """Resample time series to a different frequency."""
    df = df.set_index("ds").sort_index()
    resampled = getattr(df.resample(freq)["y"], agg)()
    return resampled.reset_index().rename(columns={"index": "ds"})


# ── 2. Model building ─────────────────────────────────────────────────────────

def build_model(
    growth:                 str   = "linear",    # "linear" | "logistic" | "flat"
    seasonality_mode:       str   = "additive",  # "additive" | "multiplicative"
    changepoint_prior_scale: float = 0.05,       # Higher = more flexible trend
    seasonality_prior_scale: float = 10.0,        # Higher = stronger seasonality
    holidays_prior_scale:   float = 10.0,
    changepoint_range:      float = 0.8,
    n_changepoints:         int   = 25,
    interval_width:         float = 0.80,        # Uncertainty interval (0.8 = 80% CI)
    daily_seasonality:      bool  = "auto",
    weekly_seasonality:     bool  = "auto",
    yearly_seasonality:     bool  = "auto",
    uncertainty_samples:    int   = 1000,
    country_holidays:       str   = None,
) -> Prophet:
    """
    Build Prophet model with configurable parameters.
    
    changepoint_prior_scale tuning:
    - 0.001-0.01: rigid trend (underfitting risk)
    - 0.05:       default, good starting point
    - 0.1-0.5:    flexible trend (overfitting risk)
    
    seasonality_mode:
    - additive:       season amplitude is constant (most time series)
    - multiplicative: season scales with trend level (revenue, growth metrics)
    """
    model = Prophet(
        growth=growth,
        seasonality_mode=seasonality_mode,
        changepoint_prior_scale=changepoint_prior_scale,
        seasonality_prior_scale=seasonality_prior_scale,
        holidays_prior_scale=holidays_prior_scale,
        changepoint_range=changepoint_range,
        n_changepoints=n_changepoints,
        interval_width=interval_width,
        daily_seasonality=daily_seasonality,
        weekly_seasonality=weekly_seasonality,
        yearly_seasonality=yearly_seasonality,
        uncertainty_samples=uncertainty_samples,
    )
    if country_holidays:
        model.add_country_holidays(country_name=country_holidays)
    return model


# ── 3. Custom seasonalities and regressors ───────────────────────────────────

def add_custom_seasonalities(
    model:        Prophet,
    seasonalities: list[dict],
) -> Prophet:
    """
    Add custom Fourier-series seasonalities.
    seasonalities = [
        {"name": "quarterly", "period": 91.25, "fourier_order": 7},
        {"name": "monthly",   "period": 30.5,  "fourier_order": 5},
    ]
    """
    for s in seasonalities:
        model.add_seasonality(**s)
    return model


def add_regressors(
    model:      Prophet,
    regressors: list[dict],
) -> Prophet:
    """
    Add external regressors (must be available for forecast horizon).
    regressors = [
        {"name": "temperature", "prior_scale": 0.5},
        {"name": "is_promo",    "prior_scale": 10},
    ]
    """
    for reg in regressors:
        model.add_regressor(**reg)
    return model


# ── 4. Training and forecasting ───────────────────────────────────────────────

def fit_and_forecast(
    model:    Prophet,
    df:       pd.DataFrame,
    periods:  int,
    freq:     str = "D",
    include_history: bool = True,
    regressor_future: pd.DataFrame = None,
) -> tuple[Prophet, pd.DataFrame]:
    """
    Fit model and generate forecast.
    Returns fitted model and forecast DataFrame.
    
    forecast columns:
    - ds, yhat:         point forecast
    - yhat_lower/upper: uncertainty interval
    - trend, trend_lower/upper
    - seasonal components (weekly, yearly, etc.)
    """
    model.fit(df)
    future = model.make_future_dataframe(
        periods=periods, freq=freq, include_history=include_history
    )

    # Add regressor values for future dates if provided
    if regressor_future is not None:
        future = future.merge(regressor_future, on="ds", how="left")

    forecast = model.predict(future)
    return model, forecast


def extract_forecast(
    forecast:     pd.DataFrame,
    last_n_rows:  int = None,
) -> pd.DataFrame:
    """Extract forecast columns from full prediction DataFrame."""
    cols = ["ds", "yhat", "yhat_lower", "yhat_upper", "trend"]
    result = forecast[cols]
    if last_n_rows:
        result = result.tail(last_n_rows)
    return result


# ── 5. Backtesting / cross-validation ────────────────────────────────────────

def backtest(
    model:    Prophet,
    df:       pd.DataFrame,
    initial:  str = "365 days",   # Training window for first cutoff
    period:   str = "90 days",    # Spacing between cutoffs
    horizon:  str = "30 days",    # Forecast horizon to evaluate
    parallel: str = "processes",  # "processes" | "threads" | None
) -> dict[str, float]:
    """
    Run time-series cross-validation and return performance metrics.
    
    initial: must be >= 2 * horizon
    period:  smaller = more cutoffs (slower, more thorough)
    horizon: evaluation window (what you care about forecasting)
    """
    model_copy = model.__class__(**{
        k: v for k, v in model.__dict__.items()
        if not k.startswith("_") and k not in {"history", "params"}
    })
    model_copy.fit(df)

    df_cv = cross_validation(
        model_copy, initial=initial, period=period,
        horizon=horizon, parallel=parallel
    )
    df_metrics = performance_metrics(df_cv)

    # Summary metrics (mean across horizons)
    summary = {
        "mae":   round(float(df_metrics["mae"].mean()), 4),
        "mape":  round(float(df_metrics["mape"].mean()), 4),
        "rmse":  round(float(df_metrics["rmse"].mean()), 4),
        "mdape": round(float(df_metrics["mdape"].mean()), 4),
    }
    return summary


# ── 6. Hyperparameter tuning ──────────────────────────────────────────────────

def tune_prophet(
    df:       pd.DataFrame,
    initial:  str = "365 days",
    period:   str = "90 days",
    horizon:  str = "30 days",
    param_grid: dict = None,
) -> dict:
    """
    Grid search over Prophet hyperparameters using CV.
    Returns best parameters by MAPE.
    """
    if param_grid is None:
        param_grid = {
            "changepoint_prior_scale": [0.01, 0.05, 0.1, 0.5],
            "seasonality_prior_scale": [0.1, 1.0, 10.0],
            "seasonality_mode":        ["additive", "multiplicative"],
        }

    all_params = [
        dict(zip(param_grid.keys(), v))
        for v in itertools.product(*param_grid.values())
    ]

    best_mape   = float("inf")
    best_params = {}

    for params in all_params:
        model = Prophet(**params, uncertainty_samples=0)
        model.fit(df)
        df_cv = cross_validation(
            model, initial=initial, period=period,
            horizon=horizon, parallel=None
        )
        df_m    = performance_metrics(df_cv, rolling_window=1)
        mape    = float(df_m["mape"].values[0])

        params_str = " ".join(f"{k}={v}" for k, v in params.items())
        print(f"  {params_str}  MAPE={mape:.4f}")

        if mape < best_mape:
            best_mape   = mape
            best_params = params

    print(f"\nBest MAPE={best_mape:.4f}: {best_params}")
    return best_params


# ── 7. Multi-series batch forecasting ────────────────────────────────────────

def forecast_multiple_series(
    series_dict: dict[str, pd.DataFrame],   # {"series_name": prophet_df}
    periods:     int = 30,
    freq:        str = "D",
    model_params: dict = None,
) -> dict[str, pd.DataFrame]:
    """
    Fit and forecast multiple independent time series.
    Returns {series_name: forecast_df}.
    """
    model_params = model_params or {}
    results = {}

    for name, df in series_dict.items():
        m = Prophet(**model_params)
        _, forecast = fit_and_forecast(m, df, periods=periods, freq=freq)
        results[name] = extract_forecast(forecast, last_n_rows=periods)
        print(f"  Forecasted: {name} ({periods} periods)")

    return results


# ── Demo ──────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("Prophet Forecasting Demo")
    print("="*50)

    # Generate synthetic daily sales data with trend + seasonality
    dates = pd.date_range("2021-01-01", "2024-01-01", freq="D")
    n     = len(dates)
    t     = np.arange(n)

    trend    = 100 + 0.05 * t
    weekly   = 10 * np.sin(2 * np.pi * t / 7)
    yearly   = 50 * np.sin(2 * np.pi * t / 365)
    noise    = np.random.normal(0, 5, n)
    y        = trend + weekly + yearly + noise

    df = make_prophet_df(dates, y)
    print(f"Dataset: {len(df)} daily observations")

    # Fit and forecast
    model = build_model(
        changepoint_prior_scale=0.05,
        seasonality_mode="additive",
        country_holidays="US",
    )
    model, forecast = fit_and_forecast(model, df, periods=90, freq="D")

    next_30 = extract_forecast(forecast, last_n_rows=30)
    print(f"\nForecasted 30 days:")
    print(next_30.head(5).to_string(index=False))

    future_yhat = next_30["yhat"].values
    print(f"\n30-day range: {future_yhat.min():.1f}{future_yhat.max():.1f}")
    print(f"90-day forecast: {forecast['yhat'].tail(90).mean():.1f} avg/day")

For the statsmodels ARIMA/SARIMA alternative when needing strict stationarity tests, ACF/PACF diagnostics, and AIC-based model selection for classical time series econometrics — ARIMA provides rigorous statistical inference while Prophet is more robust to missing data, outliers, non-stationarity, and multiple seasonal periods without requiring stationarity transformations, making it practical for business analysts and data scientists who need reliable forecasts without deep time series expertise. For the NeuralProphet/N-BEATS alternative when needing neural network components to capture complex non-linear patterns that Prophet’s additive decomposition misses — NeuralProphet extends Prophet with AR-Net autoregression while Prophet’s decomposable model (trend + seasonality + holidays) is more interpretable via plot_components, easier to incorporate domain knowledge through add_regressor, and more robust on short series (< 2 years) where neural methods overfit. The Claude Skills 360 bundle includes Prophet skill sets covering DataFrame preparation, model configuration, custom seasonalities, external regressors, holiday effects, fit and forecast, cross-validation with performance metrics, hyperparameter grid search, and multi-series batch forecasting. Start with the free tier to try time series forecasting code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free