Skip to main content

Forecast Algorithms

Tether generates demand forecasts using 11 statistical algorithms, each designed for different demand patterns and business requirements. Every algorithm operates on individual SKU-channel combinations independently, using only the historical sales data for that specific pair.
All algorithms support runtime parameter configuration. Seven of the 11 algorithms also support automatic parameter optimization to find the best settings for each SKU-channel combination.

Algorithm overview

AlgorithmBest forAuto-optimizeMin. history
Rolling Average (90-day)Stable, predictable demandNoNone
Rolling Average (120-day, Recursive)Volatile products, strategic planningNoNone
Exponentially Weighted Moving AverageTrending products, recent pattern changesYesNone
Linear TrendProducts with consistent growth or declineNoNone
Simplified SeasonalSeasonal or cyclical productsYes365 days
Simple Seasonal with Trend AdjustmentSeasonal products with growth trendsYes365 days
Seasonal Year-over-Year GrowthSeasonal products with observed YoY growthYes365 days
Rolling MomentumAccelerating or decelerating productsYes90 days
Holt-WintersComplex seasonal patterns with trendsYes365 days
SARIMAComplex time series with strong seasonalityYes365 days
Static BaselineExternal or manual forecastsNoN/A
In addition, the Consensus Model is a special model type where forecast values are entirely user-defined rather than algorithm-generated.

Rolling Average

The Rolling Average computes the simple arithmetic mean of daily sales over a historical window. It produces a flat forecast value that reflects average recent demand. How it works:
  1. Look back over the configured window (e.g., 90 days before the forecast date).
  2. Sum all sales quantities within that window — days with no sales count as zero.
  3. Divide by the window size to get the average daily demand.
When to use it: Products with stable, predictable demand that does not exhibit strong trends or seasonality.

Implementations

The default general-purpose algorithm. Computes a non-recursive average — each forecast date receives the same value based on the historical window.
ParameterDefaultDescription
window_days90Number of days to include in the average
Type ID: rolling_average Supports optimization: No
Window size trade-off: Larger windows (120+ days) produce more stable forecasts but react slowly to demand shifts. Smaller windows (30–60 days) are more responsive but more volatile.

Exponentially Weighted Moving Average (EWMA)

EWMA applies exponential weighting to historical data, giving more importance to recent observations while still considering the full window. The most recent day always has the highest weight (1.0), and each day further back is weighted by a decay factor. How it works:
  1. Look back over the configured window (default 60 days).
  2. Assign each day a weight: decay_factor^(distance_from_most_recent_day).
  3. Multiply each day’s sales by its weight, sum the weighted values, and divide by the total weight sum.
When to use it: Products experiencing trend shifts or where recent sales are a better indicator of future demand than older data.
ParameterDefaultRangeOptimizableDescription
window_days60NoNumber of days in the window
weight_factor0.80.1–0.99YesExponential decay factor — lower values create steeper decay (more recent emphasis)
Type ID: weighted_recent Supports optimization: Yes (Nelder-Mead)
A weight_factor of 0.7 emphasizes the last 2–3 weeks heavily. A value of 0.9 spreads weight more evenly across the window.

Linear Trend

Uses least-squares linear regression over a historical window to project a growth or decline trend forward. How it works:
  1. Fit a straight line (slope + intercept) through the daily sales data in the window.
  2. Project the trend line to the forecast date.
  3. If the projected value is negative, clamp it to zero.
When to use it: Products with a consistent upward or downward trajectory — for example, a product gaining market share steadily over time.
ParameterDefaultDescription
window_days120Number of days for the regression calculation
Type ID: simple_trend Supports optimization: No
Linear Trend assumes demand follows a straight line. It is sensitive to outliers and can produce unrealistic projections if demand is cyclical rather than linear.

Simplified Seasonal

Combines monthly and weekly seasonal patterns with configurable weights to capture recurring demand cycles. This algorithm uses a streamlined approach — it does not model day-of-week patterns, which reduces noise and improves stability. How it works:
  1. Extract monthly seasonal patterns (same month-of-year across prior years).
  2. Extract weekly seasonal patterns (same ISO week-of-year across prior years).
  3. Blend the two components: forecast = (weekly × weight) + (monthly × weight).
If fewer than 365 days of history are available, the algorithm automatically falls back to a 90-day Rolling Average.
ParameterDefaultRangeOptimizableDescription
weekly_weight0.80.0–1.0YesWeight for weekly seasonal component
monthly_weight0.20.0–1.0YesWeight for monthly seasonal component
Weights are normalized to sum to 1.0 during optimization. Type ID: seasonal_moving_average Supports optimization: Yes (Nelder-Mead) Minimum history: 365 days (falls back to Rolling Average with less)

Simple Seasonal with Trend Adjustment

Builds on Simplified Seasonal by adding a growth factor that blends observed year-over-year trends with a planned growth assumption. Near-term forecasts emphasize observed performance, while longer-horizon forecasts shift toward the planned growth rate. How it works:
  1. Calculate the seasonal baseline using monthly (50%) and weekly (50%) components.
  2. Compute the observed year-over-year trend from the recent observation window.
  3. Blend the observed trend with the configured planned growth rate, adjusting the blend based on how far into the forecast horizon each date falls.
  4. Apply a confidence scale based on history length:
    • Less than 365 days → falls back to Rolling Average
    • 365–729 days → 50% confidence
    • 730+ days → full confidence
ParameterDefaultOptimizableDescription
growth_factor0.15YesPlanned annual growth rate (0.15 = 15%)
adjustment_observation_window120YesDays to analyze for observed YoY trend
adjustment_horizon_window120YesDays over which to transition from observed to planned growth
initial_trend_weight0.8YesStarting weight for observed growth vs planned growth
Type ID: simple_seasonal_with_trend Supports optimization: Yes (Nelder-Mead) Minimum history: 365 days

Seasonal Year-over-Year Growth

Combines seasonal patterns with the observed year-over-year growth rate. Similar to Simplified Seasonal in its use of weekly and monthly components, but it also calculates and applies the actual YoY growth factor from historical data. How it works:
  1. If only 1–2 years of data exist, synthesize a “year 0” by duplicating the first year backward.
  2. Calculate the seasonal baseline using weekly (80%) and monthly (20%) pattern averages.
  3. Calculate the year-over-year growth factor for the forecast period.
  4. Apply growth: forecast = seasonal_baseline × (1 + growth_rate).
ParameterDefaultRangeOptimizableDescription
weekly_weight0.80.0–1.0YesWeight for weekly seasonal component
monthly_weight0.20.0–1.0YesWeight for monthly seasonal component
Weights are normalized to sum to 1.0 during optimization. Type ID: seasonal_yoy_growth Supports optimization: Yes (Nelder-Mead) Minimum history: 365 days

Rolling Momentum

Detects acceleration or deceleration in demand by comparing short-term performance against long-term performance, then projects that momentum forward. How it works:
  1. Calculate the trailing 30-day average (short-term) and the trailing 90-day average (long-term).
  2. Compute a momentum ratio: M = short-term average / long-term average.
    • M > 1.0 → demand is accelerating.
    • M < 1.0 → demand is decelerating.
    • M = 1.0 → demand is stable.
  3. Convert the momentum ratio into a daily compound growth rate.
  4. Apply a sensitivity factor to control how strongly to react to the detected momentum.
  5. Project forward using exponential growth: forecast = long_term_avg × (1 + adjusted_growth)^days_ahead.
  6. Cap the daily growth rate to prevent unrealistic projections.
ParameterDefaultRangeOptimizableDescription
short_window_days30YesDays for the short-term average
long_window_days90YesDays for the long-term average
sensitivity0.50.0–1.0YesHow strongly to react to momentum (0 = ignore, 1 = full)
max_daily_growth_cap0.02YesMaximum allowed daily growth rate (2%)
Type ID: rolling_momentum Supports optimization: Yes (Nelder-Mead) Minimum history: 90 days
Given a 90-day average of 1.22 units/day and a 30-day average of 1.67 units/day with sensitivity at 0.5:
StepCalculationResult
Momentum ratio1.67 / 1.221.36 (36% positive momentum)
Daily growth rate1.36^(1/60) − 10.52% per day
Adjusted growth0.5 × 0.52%0.26% per day
Day 30 forecast1.22 × (1.0026)^301.32
Day 90 forecast1.22 × (1.0026)^901.54

Holt-Winters (Triple Exponential Smoothing)

A classic time series method that decomposes demand into three components — level, trend, and seasonality — and updates each independently. Tether uses the multiplicative seasonal variant with a 52-week seasonal period. How it works:
  1. Initialize level, trend, and 52 weekly seasonal factors from historical data.
  2. For each period, update:
    • Level: the baseline demand value, smoothed by α.
    • Trend: the rate of growth/decline per period, smoothed by β.
    • Seasonality: weekly multiplicative factors, smoothed by γ.
  3. Project forward: forecast = (level + horizon × trend × φ^h) × seasonal_factor.
  4. The damping factor (φ) prevents unrealistic long-term trend extrapolation.
If only 1–2 years of data exist, the algorithm synthesizes a “year 0” by duplicating the first year backward to initialize seasonal factors.
ParameterDefaultRangeOptimizableDescription
alpha0.20.0–1.0YesLevel smoothing — higher values make the baseline more responsive
beta0.10.0–1.0YesTrend smoothing — higher values detect trend changes faster
gamma0.10.0–1.0YesSeasonal smoothing — higher values allow faster seasonal adaptation
phi0.950.8–1.0YesTrend damping — values below 1.0 fade the trend over longer horizons
Type ID: holt_winters Supports optimization: Yes (Nelder-Mead) Minimum history: 365 days

SARIMA

Seasonal AutoRegressive Integrated Moving Average. A powerful statistical method that models both trend and seasonal patterns through differencing and autoregressive/moving-average components. Model notation: SARIMA(p, d, q)(P, D, Q)[s]
SymbolMeaning
pNon-seasonal autoregressive order
dNon-seasonal differencing order
qNon-seasonal moving average order
PSeasonal autoregressive order
DSeasonal differencing order
QSeasonal moving average order
sSeasonal period in days (default: 365)
How it works:
  1. Apply seasonal differencing to remove yearly patterns.
  2. Apply non-seasonal differencing to remove trends.
  3. Fit an ARIMA model to the differenced series.
  4. Generate forecasts and integrate back to the original scale.
  5. Apply trend dampening to prevent unrealistic long-term extrapolation.
ParameterDefaultRangeOptimizableDescription
ar_order10–3Yes (grid)Non-seasonal AR order (p)
diff_order10–2Yes (grid)Non-seasonal differencing (d)
ma_order10–2Yes (grid)Non-seasonal MA order (q)
seasonal_ar_order10–2Yes (grid)Seasonal AR order (P)
seasonal_diff_order10–1Yes (grid)Seasonal differencing (D)
seasonal_ma_order00–1NoSeasonal MA order (Q)
seasonal_period365≥ 2NoSeason length in days (s)
trend_dampening0.950.0–1.0NoTrend fade factor for long horizons
Type ID: sarima Supports optimization: Yes (Grid Search — because ARIMA orders must be integers) Minimum history: 365 days
SARIMA uses Grid Search optimization instead of Nelder-Mead because the order parameters (p, d, q, P, D, Q) are discrete integers. Grid Search tests all combinations within the allowed ranges to find the best fit.

Static Baseline

Static Baseline directly uses uploaded forecast values without any calculation or algorithmic adjustment. It is not a forecasting algorithm in the traditional sense — it is a mechanism for importing external forecasts into Tether. How it works:
  1. Look up the uploaded baseline data for the specified label.
  2. For each forecast date, return the baseline value for that SKU-channel-date combination.
  3. No calculations, transformations, or adjustments are applied.
  4. Dates without uploaded baseline data produce no forecast output.
Type ID: static Supports optimization: No Parameters: None Use cases:
  • Import forecasts from external systems or spreadsheets
  • Use forecast data provided by customers or partners
  • Upload manually curated values for specific products or time periods
  • Bring in historical forecast data from legacy systems
The Static Baseline model requires uploaded baseline data. You must set input_source_type to baseline and specify a baseline_label when creating the model. Forecasts are only generated for dates where baseline data has been uploaded.

Consensus Model

The Consensus Model is a special model type where all forecast values are entered directly by users. Unlike the other algorithms, it does not perform any statistical calculations — it serves as a manual-input forecast that you can edit, adjust, and compare alongside algorithm-generated forecasts. The Consensus Model is typically used for collaborative demand planning where human judgment drives the final forecast numbers. You can enter values at any level of the product or time hierarchy, and the system distributes edits to individual SKU-time cells following the edit distribution rules. For details on how to enter and adjust Consensus Model values, see Forecast editing.

Parameter optimization

Tether can automatically find the best parameter values for each algorithm by testing them against historical data. This process is called parameter optimization (or auto-tune).

How optimization works

1

Split historical data

Historical sales data is split into a training set (80%) and a validation set (20%).
2

Search for best parameters

The optimizer adjusts algorithm parameters to minimize forecast error on the training data.Two optimization methods are used depending on the parameter type:
  • Nelder-Mead Simplex — for algorithms with continuous parameters (floats). Iteratively adjusts parameters to converge on the minimum error.
  • Grid Search — for algorithms with discrete parameters (integers). Tests all combinations within specified ranges. Currently used only by SARIMA.
3

Validate and store

The best parameters are evaluated against the validation set to confirm they generalize well. Optimized parameters are stored per SKU-channel combination.

Error metrics

The optimizer can minimize any of three error metrics:
MetricFormulaBest for
MSE (default)Mean of (predicted − actual)²Penalizing large errors heavily
MAEMean ofpredicted − actualMore robustness to outliers
MAPEMean ofpredicted − actual/ actual × 100%Scale-independent comparisons across SKUs

Which algorithms support optimization?

AlgorithmOptimizableMethodParameters optimized
Rolling Average (90-day)No
Rolling Average (120-day)No
EWMAYesNelder-Meadweight_factor
Linear TrendNo
Simplified SeasonalYesNelder-Meadweekly_weight, monthly_weight
Simple Seasonal with Trend AdjustmentYesNelder-Meadgrowth_factor, observation/horizon windows, initial_trend_weight
Seasonal YoY GrowthYesNelder-Meadweekly_weight, monthly_weight
Rolling MomentumYesNelder-MeadWindow sizes, sensitivity, max_daily_growth_cap
Holt-WintersYesNelder-Meadalpha, beta, gamma, phi
SARIMAYesGrid SearchAR/MA orders, seasonal orders
Static BaselineNo

Algorithm selection guide

Use this guide to choose the right algorithm based on your data patterns.
Start with Simplified Seasonal for straightforward seasonal products. If your products also exhibit year-over-year growth, use Seasonal YoY Growth or Simple Seasonal with Trend Adjustment. For complex patterns with both trend and seasonality, Holt-Winters offers the most flexibility.
Use Rolling Momentum for products experiencing demand acceleration (e.g., viral products) or deceleration (e.g., declining items). Tune the sensitivity parameter to control how aggressively the forecast reacts to momentum.
Use SARIMA for data with complex autoregressive and seasonal patterns. SARIMA is the most powerful algorithm but requires at least one year of history and is computationally intensive. Use Grid Search optimization to find the best order parameters.
Use Static Baseline to import forecasts from external systems, spreadsheets, or partner-provided data. Use the Consensus Model when human judgment should drive the forecast entirely.

Parameter tuning tips

Parameter areaGuidance
Rolling Average window30–60 days for fast-changing products. 90–120 days for general use. 180+ days for strategic planning.
EWMA decay factor0.7 for heavy recent bias. 0.8 for moderate decay. 0.9 for balanced history.
Momentum sensitivityStart at 0.5 and adjust based on accuracy. Higher values amplify momentum effects.
Holt-Winters smoothingα: 0.1–0.3 for stable series, 0.3–0.5 for volatile. β: 0.05–0.15 for most cases. γ: 0.05–0.2 for seasonal adaptation.
SARIMA ordersStart with (1,1,1)(1,1,0)[365] and use Grid Search to find the best combination.

Next steps

Forecast Admin

Configure model selection and parameters

Forecast Comparison

Compare algorithm performance side by side

Forecast Editing

Edit forecast values and work with the Consensus Model

Forecast Dashboard

View your forecasts and track accuracy