<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Archives Seasonality - OpenForecast</title>
	<atom:link href="https://openforecast.org/tag/seasonality/feed/" rel="self" type="application/rss+xml" />
	<link>https://openforecast.org/tag/seasonality/</link>
	<description>How to look into the future</description>
	<lastBuildDate>Fri, 04 Sep 2026 12:44:49 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/07/cropped-of-logo-short-1-32x32.png&amp;nocache=1</url>
	<title>Archives Seasonality - OpenForecast</title>
	<link>https://openforecast.org/tag/seasonality/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>smooth in python: Multiple Seasonal ARIMA</title>
		<link>https://openforecast.org/2026/09/10/smooth-in-python-multiple-seasonal-arima/</link>
					<comments>https://openforecast.org/2026/09/10/smooth-in-python-multiple-seasonal-arima/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Thu, 10 Sep 2026 08:01:44 +0000</pubDate>
				<category><![CDATA[ARIMA]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[smooth for Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[ADAM]]></category>
		<category><![CDATA[Seasonality]]></category>
		<category><![CDATA[smooth]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4632</guid>

					<description><![CDATA[<p>ARIMA has been a workhorse for decades. But the standard implementations quietly hard-code assumptions: one seasonal cycle, Gaussian errors, regressors handled separately etc. This is fine for textbook well-behaved data. But what do you do when you face real data? The conventional implementations (statsmodels or pmdarima in Python, stats in R) do their job well: ... <a title="smooth in python: Multiple Seasonal ARIMA" class="read-more" href="https://openforecast.org/2026/09/10/smooth-in-python-multiple-seasonal-arima/" aria-label="Read more about smooth in python: Multiple Seasonal ARIMA">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/09/10/smooth-in-python-multiple-seasonal-arima/">smooth in python: Multiple Seasonal ARIMA</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>ARIMA has been a workhorse for decades. But the standard implementations quietly hard-code assumptions: one seasonal cycle, Gaussian errors, regressors handled separately etc. This is fine for textbook well-behaved data. But what do you do when you face real data?</p>
<p>The conventional implementations (statsmodels or pmdarima in Python, stats in R) do their job well: they estimate SARIMA via likelihood, select orders automatically, and produce sensible forecasts for series with trend and one seasonality. Monthly or quarterly demand data is their home ground. The problems start when the data has more than one cycle: the classical SARIMA formulation has a slot for exactly one seasonal lag, so for the half-hourly electricity demand you would have to pick either the hour-of-day or the day-of-week cycle and discard the other.</p>
<p>MSARIMA (Multiple Seasonal ARIMA) solves this by reformulating ARIMA in the Single Source of Error (SSOE) state space form. Each AR, I, and MA element becomes a state in the model, so nothing restricts you to one seasonal lag: you can have as many as you want. In the smooth package, orders are specified per lag, matched to a lags list. Here is an example on the classical taylor series (half-hourly electricity demand in England and Wales), with two seasonal cycles:</p>
<p><code>from fcompdata import taylor<br />
from smooth import MSARIMA</p>
<p># MSARIMA(3,0,1)(0,1,1)[48](0,1,1)[336]
model = MSARIMA(<br />
    orders={"ar": [3, 0, 0], "i": [0, 1, 1], "ma": [1, 1, 1]},<br />
    lags=[1, 48, 336],<br />
    h=336, holdout=True<br />
)<br />
model.fit(taylor.y)<br />
model.predict(h=336, interval="prediction", level=0.95)</code></p>
<p>In Python, it takes only 1.5 seconds for the function to fit the model to the data and estimate its parameters, which is fast for a double-seasonal model fit to roughly four thousand observations:</p>
<figure id="attachment_4634" aria-describedby="caption-attachment-4634" style="width: 290px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/09/2026-04-30-smooth-posts-07-msarima.png&amp;nocache=1"><img fetchpriority="high" decoding="async" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/09/2026-04-30-smooth-posts-07-msarima-300x207.png&amp;nocache=1" alt="Python/R output of the double seasonal ARIMA" width="300" height="207" class="size-medium wp-image-4634" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/09/2026-04-30-smooth-posts-07-msarima-300x207.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/09/2026-04-30-smooth-posts-07-msarima.png&amp;nocache=1 632w" sizes="(max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-4634" class="wp-caption-text">Python/R output of the double seasonal ARIMA</figcaption></figure>
<p>But the smooth implementation brings several additional practical benefits.</p>
<p>First, model.fit() accepts a matrix of external regressors via xreg, estimated jointly with the ARIMA components &#8211; no separate pre-filtering step. The logic and the code are identical to ETSX, <a href="/2026/05/05/smooth-in-python-ets-with-explanatory-variables/">which I covered earlier</a>.</p>
<p>Second, you can swap the loss: loss=&#8221;GTMSE&#8221; or &#8220;MSEh&#8221; optimises the model directly on multistep errors, with the same shrinkage mechanism I discussed in <a href="/2026/08/31/smooth-in-python-multistep-losses/">the post on multistep losses</a>.</p>
<p>Third, you don&#8217;t need to stick with the Gaussian distribution &#8211; you can choose other ones if you think that, for example, Laplace is more suitable for the data (<a href="/2026/05/27/smooth-in-python-non-normal-distributions-in-ets-arima/">this post</a>).</p>
<p>And there is one more thing. Because MSARIMA now lives in the same state space framework as ETS, the two models can be combined into one and compared with each other directly via information criteria. But that deserves a post of its own, so stay tuned.</p>
<p>Read <a href="/adam/ADAMARIMA.html">Chapter 9 on ADAM ARIMA</a>.<br />
Or check out the documentation in <a href="https://github.com/openforecast-org/smooth/wiki/MSARIMA">smooth wiki</a>.</p>
<p>An why not try it yourself? <code>pip install smooth</code></p>
<p>Message <a href="https://openforecast.org/2026/09/10/smooth-in-python-multiple-seasonal-arima/">smooth in python: Multiple Seasonal ARIMA</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/09/10/smooth-in-python-multiple-seasonal-arima/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Another important Naïve method</title>
		<link>https://openforecast.org/2026/09/03/another-important-naive-method/</link>
					<comments>https://openforecast.org/2026/09/03/another-important-naive-method/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Thu, 03 Sep 2026 09:05:47 +0000</pubDate>
				<category><![CDATA[Simple Methods]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[Seasonality]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4614</guid>

					<description><![CDATA[<p>There is another forecasting method that is extremely popular, hard to beat, and has no parameters to estimate. It also has &#8220;Naïve&#8221; in its name. Do you know what I&#8217;m talking about? It is called &#8220;Seasonal Naïve&#8221;. While the simple Naïve copies the last observed actual into the future as a forecast, the seasonal one ... <a title="Another important Naïve method" class="read-more" href="https://openforecast.org/2026/09/03/another-important-naive-method/" aria-label="Read more about Another important Naïve method">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/09/03/another-important-naive-method/">Another important Naïve method</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>There is another forecasting method that is extremely popular, hard to beat, and has no parameters to estimate. It also has &#8220;Naïve&#8221; in its name. Do you know what I&#8217;m talking about?</p>
<p>It is called &#8220;Seasonal Naïve&#8221;. While the simple Naïve copies the last observed actual into the future as a forecast, the seasonal one copies the whole seasonal shape of the data and uses it as a forecast. The logic is straightforward: if you see an increase in sales every January, why not use the actual sales of January 2025 as the forecast for January 2026? Simple, easy to do, and hard to beat in some cases, especially when your demand does not have high variability.</p>
<p>What this method doesn&#8217;t do is filter out the noise in the data. This means that if you had a promotion-driven spike this February, Seasonal Naïve will happily copy it into next February&#8217;s forecast. So, if you have some distinct components in your time series and/or effects of explanatory variables on sales, Seasonal Naïve might not be a good choice. But it remains an essential benchmark for any seasonal data.</p>
<p>I actually have an anecdote related to the Seasonal Naïve. Yves Sagaert and I were working on a paper, and we decided to apply our new method to data with multiple seasonality. It worked great, better than the double seasonal exponential smoothing and ARIMA. I was really hyped and was ready to celebrate, when Yves suggested trying the Seasonal Naïve as well. It&#8217;s good that he did, because it turned out that Seasonal Naïve beat them all, including our new method, without even blinking. This was a great demonstration of a principle I had been preaching to others: if you have seasonal data, always use Seasonal Naïve as a benchmark.</p>
<p>In the Demand Forecasting Principles course in November, we cover simple methods like this one properly, including when to stop trusting them. Details and booking can be found <a href="/training/demand-forecasting-principles/">here</a>.</p>
<p>Message <a href="https://openforecast.org/2026/09/03/another-important-naive-method/">Another important Naïve method</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/09/03/another-important-naive-method/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Hans Levenbach&#8217;s classification scheme for trend/seasonal components</title>
		<link>https://openforecast.org/2026/05/18/hans-levenbach-s-classification-scheme-for-trend-seasonal-components/</link>
					<comments>https://openforecast.org/2026/05/18/hans-levenbach-s-classification-scheme-for-trend-seasonal-components/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 18 May 2026 08:01:28 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[Seasonality]]></category>
		<category><![CDATA[time series]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4145</guid>

					<description><![CDATA[<p>Here is a curious idea: if we can somehow estimate the importance of trend/seasonal components for your data, you can use this in model building and forecasting. But how can we do this first step? Hans Levenbach has an answer with his simple EDA technique. Let me explain. The core idea is simple and neat. ... <a title="Hans Levenbach&#8217;s classification scheme for trend/seasonal components" class="read-more" href="https://openforecast.org/2026/05/18/hans-levenbach-s-classification-scheme-for-trend-seasonal-components/" aria-label="Read more about Hans Levenbach&#8217;s classification scheme for trend/seasonal components">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/05/18/hans-levenbach-s-classification-scheme-for-trend-seasonal-components/">Hans Levenbach&#8217;s classification scheme for trend/seasonal components</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Here is a curious idea: if we can somehow estimate the importance of trend/seasonal components for your data, you can use this in model building and forecasting. But how can we do this first step? Hans Levenbach has an answer with his simple EDA technique. Let me explain.</p>
<p>The core idea is simple and neat. For this example, I’ll use monthly data, like the time series in this image:</p>
<figure id="attachment_4147" aria-describedby="caption-attachment-4147" style="width: 290px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-01.png&amp;nocache=1"><img decoding="async" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-01-300x180.png&amp;nocache=1" alt="" width="300" height="180" class="size-medium wp-image-4147" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-01-300x180.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-01-768x461.png&amp;nocache=1 768w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-01.png&amp;nocache=1 1000w" sizes="(max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-4147" class="wp-caption-text">Series N2568 from the M3 dataset</figcaption></figure>
<p>You can see that the data has strong seasonality, and we can qualitatively say that capturing that seasonal component correctly will probably solve the main problem in capturing the structure. But how can we quantify this?</p>
<p>All you need to do is put the data in a &#8220;wide&#8221; format, with months in rows and years in columns. Then, as Hans proposed, run a two-way ANOVA with &#8220;month&#8221; and &#8220;year&#8221; to capture variability due to year (trend) and due to month (seasonality). Roughly, we take row/column means to get mean seasonal profiles and mean annual changes (trend), as in the following two images:</p>
<figure id="attachment_4149" aria-describedby="caption-attachment-4149" style="width: 290px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-02.png&amp;nocache=1"><img decoding="async" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-02-300x180.png&amp;nocache=1" alt="Seasonal profile of the data" width="300" height="180" class="size-medium wp-image-4149" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-02-300x180.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-02-768x461.png&amp;nocache=1 768w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-02.png&amp;nocache=1 1000w" sizes="(max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-4149" class="wp-caption-text">Seasonal profile of the data</figcaption></figure>
<figure id="attachment_4148" aria-describedby="caption-attachment-4148" style="width: 290px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-03.png&amp;nocache=1"><img loading="lazy" decoding="async" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-03-300x180.png&amp;nocache=1" alt="Trend profile" width="300" height="180" class="size-medium wp-image-4148" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-03-300x180.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-03-768x461.png&amp;nocache=1 768w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-05-13-Hans-Levenbach-and-STI-03.png&amp;nocache=1 1000w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-4148" class="wp-caption-text">Trend profile</figcaption></figure>
<p>The former has no trend, the latter has no seasonality, so they can be analysed separately. Then we calculate the sums of squares of these means from the global mean to estimate variation due to months (seasonality) and years (trend). We can also calculate the sum of squares of the irregular component (what is left), giving three elements that add up to the total sum of squares.</p>
<p>Next step is trivial and straightforward: calculate the shares of each component in the total sum of squares. For our example, using <code>aov()</code> in R and then computing the total:</p>
<pre>Seasonal:  292,307,558
Trend:     176,308,365
Irregular:  33,618,630

Total:     502,234,552</pre>
<p>So, the seasonal contribution is 292,307,558 / 502,234,552 ≈ 58.2%, the trend contribution is 35.1%, and the irregular component is 6.69%.</p>
<p>Why bother? This simple EDA technique tells you roughly what to focus in forecasting. In this example, capturing seasonality correctly is roughly 60% of the story, with trend being second in importance. Hans goes further in his derivations, see <a href="https://www.linkedin.com/pulse/sticlass-scheme-classification-framework-model-levenbach-phd-cpdf-va7ae/">his LinkedIn post</a>. He also analysed M3 results at some point, explaining why some methods performed better (trend dominated the data).</p>
<p>It is worth pointing out that this approach assumes that the seasonal component does not evolve over time, which is reasonable but not always correct. And the model behind this is essentially a regression with dummy variables for year and month. Nonetheless, it is a great starting point for EDA.</p>
<p>P.S. Hans Levenbach passed away on 7 April 2026. I wasn’t sure whether to write about it and what to write about him, but I had several nice discussions with him, and I have admired his approach to forecasting: first explore the data, then build a model. His passing is a loss for the forecasting community.</p>
<p>P.P.S. You can read a bit about him on <a href="https://forecasters.org/blog/2026/04/10/hans-levenbach-1940-2026/">the IIF website</a>.</p>
<p><a href="https://youtu.be/bjXTF7gKXA8?si=m1Ym5FBDeUWbftv7">CMAF had a webinar with Hans a couple of years ago</a>. We had technical issues, but he managed to explain his idea well.</p>
<p>Message <a href="https://openforecast.org/2026/05/18/hans-levenbach-s-classification-scheme-for-trend-seasonal-components/">Hans Levenbach&#8217;s classification scheme for trend/seasonal components</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/05/18/hans-levenbach-s-classification-scheme-for-trend-seasonal-components/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Evolving seasonality</title>
		<link>https://openforecast.org/2025/09/22/evolving-seasonality/</link>
					<comments>https://openforecast.org/2025/09/22/evolving-seasonality/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 22 Sep 2025 19:21:09 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[Seasonality]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3928</guid>

					<description><![CDATA[<p>Here is another fascinating aspect of the seasonal profile in your data: it can evolve over time due to changing consumer preferences. How so? Let me explain. I&#8217;ve worked with a couple of companies where there were some examples of data with drastically changing seasonal patterns over just a few years. For example, Before Covid ... <a title="Evolving seasonality" class="read-more" href="https://openforecast.org/2025/09/22/evolving-seasonality/" aria-label="Read more about Evolving seasonality">Read more</a></p>
<p>Message <a href="https://openforecast.org/2025/09/22/evolving-seasonality/">Evolving seasonality</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Here is another fascinating aspect of the seasonal profile in your data: it can evolve over time due to changing consumer preferences. How so? Let me explain.</p>
<p>I&#8217;ve worked with a couple of companies where there were some examples of data with drastically changing seasonal patterns over just a few years. For example, Before Covid (BC), the consumer behaviour could be different than After the Disruption (AD): people started ordering online some products that they used to buy in shops. Some practitioners told me that the seasonal patterns in their data had changed so dramatically that historical data BC had become practically useless.</p>
<p>Why is this important?</p>
<p>If you don&#8217;t recognise that the seasonal patterns can change and simply use seasonal dummy variables (for example, in regression or decision trees), you&#8217;ll run into problems, as these approaches won&#8217;t capture the evolving profile. The same applies to classical decomposition (see <a href="/adam/ClassicalDecomposition.html">Section 3.2 of ADAM</a>), since it assumes a fixed seasonal structure. In fact, any model that assumes fixed seasonality would fail in this situation, and you may not even notice (see image in the post, where the model fails to capture the profile correctly because it assumes that it is fixed).</p>
<p>What can we do with that?</p>
<p>The solution is to use approaches that allow seasonality to evolve over time. ARIMA and ETS handle this via their parameters, while STL decomposition produces a dynamic seasonal profile. In regression or decision trees, you could incorporate lagged sales to partially account for this, or bring in the seasonal component from STL/ETS as an additional feature.</p>
<p>All good? Not quite, because there is a nasty small grey elephant hidden in this room.</p>
<p>Even if your chosen method allows seasonality to evolve, you must ensure that forecasting uncertainty reflects this properly. If the seasonal pattern in your training set changed drastically, what prevents it from shifting again in the test set? This is particularly critical if you need predictive distributions, such as for setting safety stock levels or generating prediction intervals. Ignoring the fact that the seasonality might change further could make your predictive distribution narrower than expected, leading to potential lost sales.</p>
<p>The good news: ARIMA and ETS handle this naturally, as components&#8217; uncertainty translates directly to the holdout variance. In ML, it is more complicated, because you would need to invest time in proper feature engineering to explicitly capture the potential seasonality changes. Unfortunately, I haven&#8217;t done much in the latter direction, so I cannot give you a good recipe. Any thoughts what to do here?</p>
<p>And what do you do in the situation like that?</p>
<p>Message <a href="https://openforecast.org/2025/09/22/evolving-seasonality/">Evolving seasonality</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2025/09/22/evolving-seasonality/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Challenges related to seasonal data: shifting seasonality</title>
		<link>https://openforecast.org/2025/04/07/challenges-related-to-seasonal-data/</link>
					<comments>https://openforecast.org/2025/04/07/challenges-related-to-seasonal-data/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 07 Apr 2025 12:54:49 +0000</pubDate>
				<category><![CDATA[Applied forecasting]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[Seasonality]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3814</guid>

					<description><![CDATA[<p>There are many different issues with capturing seasonality in time series. In this short post, I&#8217;d like to discuss one of the most annoying ones. I&#8217;m talking about the seasonal pattern that shifts over time. What I mean is that, for example, instead of having the standard number of observations in the cycle (e.g., 24 ... <a title="Challenges related to seasonal data: shifting seasonality" class="read-more" href="https://openforecast.org/2025/04/07/challenges-related-to-seasonal-data/" aria-label="Read more about Challenges related to seasonal data: shifting seasonality">Read more</a></p>
<p>Message <a href="https://openforecast.org/2025/04/07/challenges-related-to-seasonal-data/">Challenges related to seasonal data: shifting seasonality</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>There are many different issues with capturing seasonality in time series. In this short post, I&#8217;d like to discuss one of the most annoying ones.</p>
<p>I&#8217;m talking about the seasonal pattern that shifts over time. What I mean is that, for example, instead of having the standard number of observations in the cycle (e.g., 24 hours in a day), in some cases you can have more or fewer of them. How is that possible?</p>
<p>One of these issues is the Daylight Saving Time (DST) change. The original idea of DST was to reduce energy consumption because daylight in summer is longer than in winter (there&#8217;s a nice and long article on Wikipedia about it). Because of this, many countries introduced a time shift: in spring, the clock is moved forward by one hour, while in autumn it goes back. This idea had a reasonable motivation at the beginning of the 20th century, but I personally think that as we&#8217;ve progressed as a society, it has lost its value. While this is already extremely annoying on its own, a bit unhealthy (several studies report an increased risk of heart attacks), and a torture for parents with small kids (the little ones don&#8217;t understand that it&#8217;s not 7am yet), it also introduces a modelling challenge: two days in the year do not have 24 hours. In spring, we have 23 hours, while in autumn we have 25. Standard classical forecasting approaches (such as ETS/ARIMA, regression, STL or classical decomposition) break in this case, because by default they assume that a specific pattern repeats itself every 24 hours. The issue arises because business cycles are tuned to working hours, not to the movement of the sun &#8211; people come to work at 9am, no matter how many hours are in the day.</p>
<p>Another challenge is leap years. While DST is totally man-made, leap years occur because the Earth orbits the sun approximately every 365.25 days. To avoid drifting too far from reality, our calendars include one extra day every four years (29th February). This addresses the issue but also means that one year has 366 days instead of 365. Once again, conventional models relying on fixed periodicity fail.</p>
<p>There are several ways to handle this, all with their own advantages and disadvantages:</p>
<ol>
<li>Fix the data. In the case of DST, this means removing one of the duplicated hours during the autumn time change and adding one during the spring shift. For leap years, it means dropping the 29th of February. This is easy to do, but breaks the structure and might cause issues when we have DST/leap year in the holdout sample.</li>
<li>Introduce more complex components, such as Fourier-based ones, to capture the shift in the data. This works well for leap years but doesn&#8217;t address the DST issue. <a href="https://doi.org/10.1016/j.energy.2015.02.100)">Harmonic regressions</a> and <a href="https://doi.org/10.1198/jasa.2011.tm09771">TBATS</a> do this, for example.</li>
<li><a href="https://openforecast.org/adam/MultipleFrequenciesDSTandLeap.html">Shift seasonal indices</a> when the issue happens &#8211; for example, having two indices for 1am when the switch to winter time occurs.</li>
</ol>
<p>In R, I’ve developed the <code>temporaldummy()</code> function in the <code>greybox</code> package to introduce correct dummy variables for data with shifting seasonality, and I’ve incorporated method (3) into the <code>adam()</code> function from the smooth package. You can read more about these here: https://openforecast.org/adam/MultipleFrequenciesDSTandLeap.html</p>
<p>Are there any other strategies? Which one do you prefer?</p>
<p>BTW, Kandrika Pritularga and I are running a course on Demand Forecasting Principles with Examples in R. We’ll discuss some of these aspects there. Read more about it <a href="https://lancaster.ac.uk/centre-for-marketing-analytics-and-forecasting/grow-with-us/demand-forecasting-with-r/">here</a>.</p>
<p>Message <a href="https://openforecast.org/2025/04/07/challenges-related-to-seasonal-data/">Challenges related to seasonal data: shifting seasonality</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2025/04/07/challenges-related-to-seasonal-data/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Naming conventions for seasonality types</title>
		<link>https://openforecast.org/2025/03/26/naming-conventions-for-seasonality-types/</link>
					<comments>https://openforecast.org/2025/03/26/naming-conventions-for-seasonality-types/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Wed, 26 Mar 2025 11:44:00 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[Seasonality]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3809</guid>

					<description><![CDATA[<p>In forecasting, the term seasonality doesn’t always mean what you think it does. It encompasses more than just patterns repeating from one season to the next. In fact, seasonality covers a wide range of periodic behaviors, and can have some issues associated with the naming conventions. Should we discuss? First things first: when we say ... <a title="Naming conventions for seasonality types" class="read-more" href="https://openforecast.org/2025/03/26/naming-conventions-for-seasonality-types/" aria-label="Read more about Naming conventions for seasonality types">Read more</a></p>
<p>Message <a href="https://openforecast.org/2025/03/26/naming-conventions-for-seasonality-types/">Naming conventions for seasonality types</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In forecasting, the term seasonality doesn’t always mean what you think it does. It encompasses more than just patterns repeating from one season to the next. In fact, seasonality covers a wide range of periodic behaviors, and can have some issues associated with the naming conventions. Should we discuss?</p>
<p>First things first: when we say &#8220;seasonality&#8221; in forecasting, we mean any pattern that repeats periodically. If you mention monthly seasonality, most people will understand that you’re referring to a pattern repeating every 12 observations. Similarly, quarterly seasonality is widely recognized. However, beyond these two simple cases, ambiguity creeps in.</p>
<p>For example, if you describe your data as having &#8220;weekly&#8221; seasonality, do you mean that you’re working with weekly data and observe similar patterns every 52 weeks? Or are you dealing with daily data, where the pattern repeats every 7 days? The same issue applies to the term &#8220;daily&#8221; seasonality, which can refer to a pattern within daily data or a repeating pattern across multiple days.</p>
<p>Furthermore, the more granular your data, the more potential seasonal profiles you can have. For daily data, you may observe seasonality at 7-day (weekly) and 365-day (yearly) intervals. For hourly data, you could have three seasonal patterns: 24 hours, 168 hours (24 × 7), and 8,760 hours (24 × 365). An example of such data is shown in the image attached to this post.</p>
<p>Some people use the prefix &#8220;intra&#8221; to indicate patterns within a given frequency, but I still find this confusing. For example, intraweekly only indicates that a pattern exists within the week but doesn’t specify the frequency: it could refer to either 7 days or 168 hours.</p>
<p>That’s why I personally prefer the &#8220;A of B&#8221; naming scheme for seasonality. For example, &#8220;week of year&#8221; seasonality clearly denotes a pattern repeating every 52 observations. &#8220;Day of week&#8221; clearly refers to a 7-observation pattern. This format is more precise and less ambiguous than &#8220;weekly&#8221; or &#8220;intraweekly&#8221; seasonality. &#8220;Hour of year&#8221;, &#8220;half-hour of week&#8221;, &#8220;minute of day&#8221; etc are all straightforward and easy to understand.</p>
<p>And what naming conventions do you use?</p>
<p>P.S. Kandrika Pritularga and I are running the course &#8220;Demand Forecasting Principles with Examples in R&#8221; again, where we’ll discuss some of these and related aspects in detail. You can read more about the course and sign up for it <a href="https://lancaster.ac.uk/centre-for-marketing-analytics-and-forecasting/grow-with-us/demand-forecasting-with-r/">here</a> and <a href="https://online-payments.lancaster-university.co.uk/product-catalogue/courses/lancaster-university-management-school-lums/centre-for-marketing-analytics-forecasting-cmaf/demand-forecasting-principles-with-examples-in-r">here</a> respectively.</p>
<p>Message <a href="https://openforecast.org/2025/03/26/naming-conventions-for-seasonality-types/">Naming conventions for seasonality types</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2025/03/26/naming-conventions-for-seasonality-types/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Seasonal or not?</title>
		<link>https://openforecast.org/2024/05/15/seasonal-or-not/</link>
					<comments>https://openforecast.org/2024/05/15/seasonal-or-not/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Wed, 15 May 2024 13:00:38 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[Seasonality]]></category>
		<category><![CDATA[time series]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3575</guid>

					<description><![CDATA[<p>Not every pattern that appears seasonal is genuinely seasonal. This means you don&#8217;t always require a seasonal model when you see repetitive patterns with fixed periodicity. How come? First things first, in forecasting, the term &#8220;seasonality&#8221; refers to any natural pattern repeating with some periodicity. For example, if you work in a hospital with A&#038;E ... <a title="Seasonal or not?" class="read-more" href="https://openforecast.org/2024/05/15/seasonal-or-not/" aria-label="Read more about Seasonal or not?">Read more</a></p>
<p>Message <a href="https://openforecast.org/2024/05/15/seasonal-or-not/">Seasonal or not?</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Not every pattern that appears seasonal is genuinely seasonal. This means you don&#8217;t always require a seasonal model when you see repetitive patterns with fixed periodicity. How come?</p>
<p>First things first, in forecasting, the term &#8220;seasonality&#8221; refers to any natural pattern repeating with some periodicity. For example, if you work in a hospital with A&#038;E attendance, you know that every Monday has higher demand than other days, while weekends tend to have lower demand. This is a well known phenomenon: <a href="https://digital.nhs.uk/data-and-information/publications/statistical/hospital-accident--emergency-activity/2019-20/time-of-day">people have fun over the weekend and then go to hospital first thing in the morning of the work week</a>, so if you don&#8217;t want to get stuck in the hospital, don&#8217;t injure yourselves over the weekend!</p>
<p>Anyway, back to the main topic of this post!</p>
<p>Consider the following example:</p>
<figure id="attachment_3576" aria-describedby="caption-attachment-3576" style="width: 290px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2024/05/2024-05-14-Seasonality.png&amp;nocache=1"><img loading="lazy" decoding="async" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2024/05/2024-05-14-Seasonality-300x161.png&amp;nocache=1" alt="Seemingly seasonal time series" width="300" height="161" class="size-medium wp-image-3576" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2024/05/2024-05-14-Seasonality-300x161.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2024/05/2024-05-14-Seasonality.png&amp;nocache=1 640w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-3576" class="wp-caption-text">Seemingly seasonal time series</figcaption></figure>
<p>This is a daily data. Is it seasonal? Without context, you might assume so: there&#8217;s a midweek peak followed by a decline, repeating weekly, so it must be seasonal, right? But what if I told you that this data is daily LinkedIn impressions of my posts? The peaks coincide with posts releases, and it is hard to tell from the image, but I released first three posts on Thursdays and then switched to Wednesdays, shifting peaks one day forward. So, this is not a seasonal data, but instead it is a classical life cycle (which can be described, for example, by the <a href="https://doi.org/10.1287/mnsc.15.5.215">Bass model</a>), repeating every week. It would be seasonal if the impressions happened naturally without me releasing anything. For example, number of visitors of my website has natural seasonality, because they happen without my interventions:</p>
<figure id="attachment_3577" aria-describedby="caption-attachment-3577" style="width: 290px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2024/05/2024-05-14-Seasonality-website.png&amp;nocache=1"><img loading="lazy" decoding="async" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2024/05/2024-05-14-Seasonality-website-300x130.png&amp;nocache=1" alt="The series with natural seasonality" width="300" height="130" class="size-medium wp-image-3577" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2024/05/2024-05-14-Seasonality-website-300x130.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2024/05/2024-05-14-Seasonality-website.png&amp;nocache=1 734w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-3577" class="wp-caption-text">The series with natural seasonality</figcaption></figure>
<p>Bringing this to a business context, I have encountered several times the &#8220;spurious seasonality&#8221;. For example, one company, working with weekly data, used a seasonal model with periodicity of 4, because they noticed that at the end of each month, people get their salary and spend it, increasing the sales of the company. However this is not true seasonality, but rather a calendar event that happens seemingly periodically, on a specific day of month (not necessarily the same one).</p>
<p>Why is this important?</p>
<p>Relying on a seasonal model (like seasonal ETS or ARIMA) in such cases poses risks. If the periodicity shifts (e.g., salaries received on a different week), the model will produce misaligned forecasts (e.g., predicting an earlier peak). To address this, you should model such events with explanatory variables instead of seasonal indices. This way you will be able to control the timing of the event in your model and adjust it if needed.</p>
<p>So, next time you see a pattern that looks seasonal, think whether it happens naturally, or whether you are dealing with the spurious seasonality. Remember, the context is always important!</p>
<p>Message <a href="https://openforecast.org/2024/05/15/seasonal-or-not/">Seasonal or not?</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2024/05/15/seasonal-or-not/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
