ds@mcpanalytics.aiEmail your data and your question and get an answer about your own data, with the method shown.Email your data and question. Get an answer.
WHITEPAPER

Theta Method Forecasting: How It Works and When It Fits

Updated October 2026

9 min read MCP Analytics Team

Executive Summary

The Theta method is a simple forecasting method that fits a straight-line trend and a simple exponential smoothing (SES) forecast and averages the two. It did well in the M3 forecasting competition and is cheap to run, so it is a common baseline for series that trend without strong irregular patterns.

This paper is a method guide. It explains how Theta lines are built, how the method relates to SES with drift, and which kinds of series it suits or does not. The only numbers in it come from a simulation in section 4, whose code is shown; they describe that simulated setup and are not a claim about any real data set.

To see where your own measure is heading, with a likely range, try the free forecasting tool.

Key Points

  • Theta is SES with a drift. Hyndman and Billah (2003) showed the standard method equals simple exponential smoothing with a drift term equal to half the slope of the linear trend.
  • It handled trend and seasonality well in the simulation. On simulated trending series its error was about three quarters of the SES error, and on strongly seasonal series (with its built-in seasonal adjustment) about a quarter.
  • It struggled after a trend reversal. When the trend changed direction shortly before the forecast origin, Theta kept extrapolating the old slope and was worse than a naive forecast.
  • Intermittent demand needs its own method. On series with many zeros the simple methods were similar in this run; Croston-type methods are designed for that case and should be compared on your data.

Recommendation: use Theta as a quick, strong baseline, compare it with naive, SES and a seasonal method on a holdout period, and check the recent trend before trusting its extrapolation.

1. Introduction

1.1 Why a Simple Method

Forecasting competitions have repeatedly found that simple, well-chosen methods are hard to beat on average, because they do not chase noise in the history. A simple method is also cheap to run across thousands of series and easy to explain. That does not make it right for every series, which is why a baseline needs to be compared, not assumed.

1.2 What This Paper Covers

  • How Theta lines are constructed, with a small example you can run
  • How the standard method combines two lines and how it relates to SES with drift
  • A reproducible simulation of where Theta helps and where it does not
  • Practical guidance for using it as a baseline

2. Background

2.1 The M3 Competition

The M3 competition (Makridakis and Hibon, 2000) compared forecasting methods on 3,003 real series from several domains and frequencies. The Theta method of Assimakopoulos and Nikolopoulos (2000) was among its best-performing methods, with the ranking depending on the accuracy measure and the type of series. That is a statement about that competition's data; it does not say Theta is best on any given series.

2.2 Decomposition Ideas

Forecasting methods that split a series into interpretable parts, such as trend, seasonality and remainder, make their assumptions explicit and testable. The Theta method works on the series' curvature: it builds new series by shrinking or amplifying the local fluctuations around the trend, forecasts each, and recombines them.

3. Approach

3.1 Theta Lines

For a series Yt with an ordinary least squares trend line a + b*t, the Theta line with parameter theta is

Y'(theta)_t = theta * Y_t + (1 - theta) * (a + b * t)

With theta = 1 this is the original series. With theta = 0 it is the straight trend line. With theta = 2 the local curvature, meaning the deviations of the series from its trend, is doubled. A small example:

import numpy as np

# Theta lines for a short series: theta = 0 is the OLS trend line, theta = 1 the data, theta = 2 doubles the local curvature
y = np.array([10., 12., 11., 14., 15., 14., 17., 18.])
t = np.arange(len(y))
b, a = np.polyfit(t, y, 1)
trend = a + b * t
for theta in (0, 1, 2):
    line = theta * y + (1 - theta) * trend
    print(f"theta={theta}:", np.round(line, 1))
theta=0: [10.1 11.2 12.2 13.3 14.4 15.5 16.6 17.7]
theta=1: [10. 12. 11. 14. 15. 14. 17. 18.]
theta=2: [ 9.9 12.8  9.8 14.7 15.6 12.5 17.4 18.3]

3.2 The Standard Method

The standard Theta forecast is the average of two forecasts: the theta = 0 line extrapolated as a straight line, and the theta = 2 line forecast with simple exponential smoothing. Seasonal series are typically seasonally adjusted first, and the seasonal pattern is put back afterwards. Hyndman and Billah (2003) showed that this standard forecast equals SES applied to the original series plus a drift equal to half the slope b of the linear trend, which explains why it behaves like a damped, smoothed trend follower.

3.3 What It Assumes

  • A roughly stable linear trend over the history, extended into the future.
  • A level that is better estimated by exponentially weighted averaging than by the last value alone.
  • For seasonal data, a seasonal pattern that the adjustment step can estimate and that stays stable.

It does not model intermittent demand, structural breaks or external drivers.

3.4 Evaluating It

Compare against naive and SES on a holdout period that follows the training period in time. A scale-free measure such as the mean absolute scaled error (MASE), which divides forecast error by the in-sample error of a one-step naive forecast, works across series of different sizes and is defined when the actual values include zeros.

4. A Reproducible Simulation

The simulation generates four kinds of series, 200 of each, with 72 monthly-style observations of history and a 12-step holdout: a linear trend with noise; a strongly seasonal series with a slight trend; a series whose trend reverses six points before the forecast origin; and intermittent counts (many zeros). It compares naive, SES and Theta (statsmodels ThetaModel with period 12), and Croston with the Syntetos-Boylan correction for the intermittent series only, using MASE.

import warnings
import numpy as np
from statsmodels.tsa.forecasting.theta import ThetaModel
from statsmodels.tsa.holtwinters import SimpleExpSmoothing

warnings.filterwarnings("ignore")
H, N = 12, 72   # forecast horizon and history length (monthly-style series)

def croston_sba(y, h, alpha=0.1):
    """Croston's method with the Syntetos-Boylan bias correction."""
    size, interval, q, last = None, None, 1, 0
    for v in y:
        if v > 0:
            size = v if size is None else size + alpha * (v - size)
            interval = q if interval is None else interval + alpha * (q - interval)
            q = 1
        else:
            q += 1
    f = 0.0 if size is None else (1 - alpha / 2) * size / interval
    return np.full(h, f)

def make_series(kind, rng):
    t = np.arange(N + H)
    noise = rng.normal(size=N + H)
    if kind == "trend + noise":
        return 50 + 0.8 * t + 6 * noise
    if kind == "strong seasonal":
        return 100 + 0.2 * t + 25 * np.sin(2 * np.pi * t / 12) + 5 * noise
    if kind == "trend break":
        return 50 + 0.8 * t - 1.6 * np.maximum(t - (N - 6), 0) + 4 * noise
    if kind == "intermittent":
        return rng.poisson(0.35, size=N + H) * rng.integers(1, 6, size=N + H)

def forecasts(y, kind):
    out = {"naive": np.full(H, y[-1]),
           "SES": SimpleExpSmoothing(y, initialization_method="estimated").fit().forecast(H),
           "Theta": ThetaModel(y, period=12).fit().forecast(H).to_numpy() if y.std() > 0 else np.full(H, y[-1])}
    if kind == "intermittent":          # Croston is built for intermittent demand only
        out["Croston-SBA"] = croston_sba(y, H)
    return out

def mase(y_train, y_test, f):
    scale = np.mean(np.abs(np.diff(y_train)))
    return np.mean(np.abs(y_test - f)) / scale

rng = np.random.default_rng(2026)
print("mean MASE over 200 series per row (lower is better; 1.0 = in-sample one-step naive error)")
names = ["naive", "SES", "Theta", "Croston-SBA"]
print(f"{'series type':16s}" + "".join(f"{n:>13s}" for n in names))
for kind in ("trend + noise", "strong seasonal", "trend break", "intermittent"):
    scores = {n: [] for n in names}
    for _ in range(200):
        s = make_series(kind, rng)
        train, test = s[:N], s[N:]
        for n, f in forecasts(train, kind).items():
            scores[n].append(mase(train, test, f))
    print(f"{kind:16s}" + "".join(f"{np.mean(scores[n]):13.2f}" if scores[n] else f"{'-':>13s}" for n in names))

Output:

mean MASE over 200 series per row (lower is better; 1.0 = in-sample one-step naive error)
series type             naive          SES        Theta  Croston-SBA
trend + noise            1.25         1.21         0.93            -
strong seasonal          1.96         1.96         0.52            -
trend break              1.51         1.52         2.10            -
intermittent             1.07         0.92         0.93         0.92

In this setup Theta clearly beat the flat forecasts on the trending and seasonal series, with the seasonal adjustment doing much of the work in the second row. After the trend reversal it was worse than both flat forecasts, because the extrapolated slope pointed the wrong way. On intermittent counts the three methods were close, and none is a verdict on how they compare on real intermittent demand, where series differ widely in how often and how much demand occurs. Other designs, such as different noise, trend strength or break timing, give different numbers.

5. Practical Guidance

Point 1: Use It as a Baseline

Theta is cheap to fit and often competitive, so it is a sensible first benchmark. Any more complex method should have to beat it on a holdout period.

Point 2: Check the Recent Trend

Plot the last stretch of the series against the fitted trend. If the direction has changed recently, Theta's extrapolation will lag, as in the break scenario above. Consider refitting on the recent window or switching to a method that adapts faster.

Point 3: Deal With Seasonality Explicitly

Check that the seasonal adjustment is switched on and that the period is right. Long periods or several overlapping seasonal cycles are outside what the standard adjustment handles; compare with a method designed for them.

Point 4: Treat Intermittent Series Separately

For series with many zeros, compare Theta with Croston-type methods on a holdout using a measure suited to zeros, such as MASE, and look at forecast quality for the periods where demand occurs.

Point 5: Report Uncertainty

A point forecast needs a range. Use the prediction interval the implementation provides, or an empirical interval from holdout errors, and check on past data how often actual values fall inside it.

6. Conclusion

The Theta method is a smoothed trend follower: SES plus half the linear slope. It is a strong, inexpensive baseline when the trend is stable and seasonality is regular, and it fails predictably when the trend changes direction or demand is intermittent. Compare it with naive, SES and an alternative on a holdout before relying on it.

Your turn

Bring your own data and the question you actually need answered.

MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai

Frequently Asked Questions

What is the Theta method?

A forecasting method that averages the extrapolated linear trend (theta = 0) with an SES forecast of the line whose curvature is doubled (theta = 2). It is equivalent to simple exponential smoothing with a drift of half the linear trend slope.

Does Theta handle seasonality?

Implementations typically seasonally adjust the series first, test whether seasonality is present, and reapply the pattern to the forecast. Long periods and multiple seasonal cycles are not covered by that adjustment.

When should I not use Theta?

When the trend has recently changed direction, when demand is intermittent, or when external drivers matter. Compare against naive, SES and an alternative on a holdout period.

How was Theta shown to perform?

It was among the strongest methods in the M3 competition (3,003 series). That result is specific to that data, so check it on your own series.

How do I evaluate a forecast of a series with zeros?

Use a scale-free measure that is defined at zero, such as MASE, rather than percentage errors, which break when actual values are zero.

References & Further Reading

  • Assimakopoulos, V., & Nikolopoulos, K. (2000). The theta model: a decomposition approach to forecasting. International Journal of Forecasting, 16(4), 521-530.
  • Makridakis, S., & Hibon, M. (2000). The M3-Competition: results, conclusions and implications. International Journal of Forecasting, 16(4), 451-476.
  • Hyndman, R. J., & Billah, B. (2003). Unmasking the Theta method. International Journal of Forecasting, 19(2), 287-290.
  • Hyndman, R. J., & Athanasopoulos, G. (2021). Forecasting: Principles and Practice (3rd ed.). OTexts.
  • Croston, J. D. (1972). Forecasting and stock control for intermittent demands. Operational Research Quarterly, 23(3), 289-303.
  • Syntetos, A. A., & Boylan, J. E. (2005). The accuracy of intermittent demand estimates. International Journal of Forecasting, 21(2), 303-314.