Skip to content

Instantly share code, notes, and snippets.

@danielhaim1
Last active March 29, 2023 09:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielhaim1/e9ee7187f238b72590b5d634523cd631 to your computer and use it in GitHub Desktop.
Save danielhaim1/e9ee7187f238b72590b5d634523cd631 to your computer and use it in GitHub Desktop.
Holt-Winters Forecasting Algorithm
function holtWinters(alpha, beta, gamma, period, data) {
let seasonals = {};
let r = [];
let initialSeasonals = [];
let detrended = [];
let forecast = [];
let dataPoints = data.length;
let avgSmooth = [];
let trendSmooth = [];
let seasonalSmooth = [];
//initialize seasonals to the average of each cycle
for (let i = 0; i < period; i++) {
seasonals[i] = [];
for (let j = i; j < dataPoints; j += period) {
seasonals[i].push(data[j]);
}
initialSeasonals[i] = (seasonals[i].reduce((a, b) => a + b, 0) / seasonals[i].length);
}
//initialize first level of smoothed averages
for (let i = 0; i < period; i++) {
avgSmooth[i] = (data.slice(i, i + period).reduce((a, b) => a + b, 0) / period);
}
//initialize first level of smoothed trends
for (let i = 0; i < period; i++) {
trendSmooth[i] = ((data[period + i] - data[i]) / period);
}
//initialize seasonalSmooth
for (let i = 0; i < period; i++) {
seasonalSmooth[i] = initialSeasonals[i] - avgSmooth[i];
}
//determine r
for (let i = 0; i < dataPoints - period; i++) {
r[i] = data[period + i] - (avgSmooth[i] + trendSmooth[i]);
}
//smooth the detrended values
for (let i = 0; i < dataPoints - period; i++) {
detrended[i] = (alpha * (data[period + i] - seasonalSmooth[i])) + ((1 - alpha) * (detrended[i - 1] || r[0]));
}
//smooth the trend
for (let i = 0; i < period; i++) {
trendSmooth[period + i] = (beta * (detrended[i] - detrended[i - period])) + ((1 - beta) * trendSmooth[i]);
}
//smooth the seasonals
for (let i = 0; i < period; i++) {
seasonalSmooth[i] = (gamma * (data[period + i] - avgSmooth[i] - detrended[i])) + ((1 - gamma) * seasonalSmooth[i]);
}
//calculate the forecast
for (let i = 0; i < period; i++) {
forecast[i] = avgSmooth[i] + ((i + 1) * trendSmooth[period + i]) + seasonalSmooth[i - period];
}
return forecast;
}
// Input data for the time series
const data = [
100,
120,
130,
140,
150,
160,
170,
180,
190,
200,
210,
220,
230,
240,
250,
260,
270,
280,
290,
300,
];
// Apply Holt-Winters method with alpha=0.2, beta=0.1, gamma=0.1, and period=4
const forecast = hw(data, {
alpha: 0.2,
beta: 0.1,
gamma: 0.1,
period: 4,
forecastLength: 5,
});
// Output the forecast values
console.log(forecast);
// Level: L(t) = alpha * Y(t) + (1 - alpha) * (L(t-1) + T(t-1))
// Trend: T(t) = beta * (L(t) - L(t-1)) + (1 - beta) * T(t-1)
// Seasonality: S(t) = gamma * (Y(t) - L(t)) + (1 - gamma) * S(t-m)
// F(t+h) = L(t) + h * T(t) + S(t-m+1+(h-1)modm)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment