<?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 Social media - OpenForecast</title>
	<atom:link href="https://openforecast.org/category/social-media/feed/" rel="self" type="application/rss+xml" />
	<link>https://openforecast.org/category/social-media/</link>
	<description>How to look into the future</description>
	<lastBuildDate>Fri, 04 Sep 2026 11:54:14 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</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 Social media - OpenForecast</title>
	<link>https://openforecast.org/category/social-media/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<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>smooth in python: Multistep losses</title>
		<link>https://openforecast.org/2026/08/31/smooth-in-python-multistep-losses/</link>
					<comments>https://openforecast.org/2026/08/31/smooth-in-python-multistep-losses/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 31 Aug 2026 08:47:20 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[smooth for Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[ADAM]]></category>
		<category><![CDATA[ARIMA]]></category>
		<category><![CDATA[ETS]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[Loss functions]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4605</guid>

					<description><![CDATA[<p>Why train a forecasting model on one-step-ahead errors when you care about 10-step-ahead accuracy? This is the core motivation behind multistep losses in dynamic models. This has connection with the so-called &#8220;direct forecasting strategy&#8221;. And here what it is and how to work with it in Python. Conventional maximum likelihood estimation minimises one-step-ahead errors. It ... <a title="smooth in python: Multistep losses" class="read-more" href="https://openforecast.org/2026/08/31/smooth-in-python-multistep-losses/" aria-label="Read more about smooth in python: Multistep losses">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/08/31/smooth-in-python-multistep-losses/">smooth in python: Multistep losses</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Why train a forecasting model on one-step-ahead errors when you care about 10-step-ahead accuracy? This is the core motivation behind multistep losses in dynamic models. This has connection with the so-called &#8220;direct forecasting strategy&#8221;. And here what it is and how to work with it in Python.</p>
<p>Conventional maximum likelihood estimation minimises one-step-ahead errors. It works well in many standard situations and produces quite robust models. But in practice, you are rarely interested in just the next observation. Supply chains operate on lead times. Budgets are planned quarterly. The model you trained on one-step-ahed forecast is not the model that minimises your actual decision-relevant error.</p>
<p><strong>Multistep losses address this directly</strong>. Instead of minimising \(\mathrm{MSE}_1\), they minimise errors computed \(h\) steps ahead from every in-sample point. The key theoretical result (<a href="/2023/08/09/multi-step-estimators-and-shrinkage-effect-in-time-series-models/">Svetunkov et al., 2023</a>) is that this implies *shrinkage* of smoothing parameters towards zero — the model becomes less stochastic, less reactive to noise, and more stable across longer horizons. Shrinkage strength grows with \(h\) and weakens as sample size increases.</p>
<p>ADAM supports several multistep losses, each with a different trade-off:</p>
<ul>
<li><strong>MSEh</strong> — minimises the \(h\)-step-ahead variance only; strongest shrinkage, simplest interpretation;</li>
<li><strong>TMSE</strong> — sums \(\mathrm{MSE}_j\) for \(j=1,&#8230;,h\), i.e. sum of the MSEs between 1 and h steps ahead; balances all horizons but is dominated by longer-horizon errors;</li>
<li><strong>GTMSE</strong> — takes the log of each \(\mathrm{MSE}_j\) before summing; equalises the influence of short and long horizons, milder shrinkage;</li>
<li><strong>MSCE</strong> — minimises cumulative forecast error; directly relevant for inventory decisions with lead time \(h\);</li>
<li><strong>GPL</strong> — the full General Predictive Likelihood; accounts for the entire covariance structure of multistep errors and encompasses all the above.</li>
</ul>
<p>All of these are accessible in the Python <code>smooth</code> package with a single parameter change. Here is an example of the code with GTMSE:</p>
<pre class="decode">from fcompdata import AirPassengers
from smooth import ADAM

model = ADAM(model="AAA", lags=12, loss="GTMSE", h=12)
model.fit(AirPassengers.y)
model.predict(h=10)</pre>
<p>The <code>h</code> parameter sets the horizon over which multistep errors are evaluated during estimation. This allows connecting the loss with the specific decision horizon better. The image in the post shows the ETS model fit and forecasts, when estimated with several different losses, including the conventional one.</p>
<p>One practical note: on small samples, MSEh and MSCE can produce noticeably biased parameter estimates (closer to zero) due to strong shrinkage. GTMSE tends to be a safer default for small samples.</p>
<p>Read more about these and other losses in the <a href="/adam/multistepLosses.html">ADAM monograph</a> or in the <a href="https://github.com/openforecast-org/smooth/wiki">wiki of the package</a>.</p>
<p>Message <a href="https://openforecast.org/2026/08/31/smooth-in-python-multistep-losses/">smooth in python: Multistep losses</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/08/31/smooth-in-python-multistep-losses/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why Naïve is popular and important</title>
		<link>https://openforecast.org/2026/08/27/why-naive-is-popular-and-important/</link>
					<comments>https://openforecast.org/2026/08/27/why-naive-is-popular-and-important/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Thu, 27 Aug 2026 09:03:02 +0000</pubDate>
				<category><![CDATA[Simple Methods]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[Competitions]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4599</guid>

					<description><![CDATA[<p>There is one forecasting method that appears more often than any other in competitions and evaluations. An experienced forecaster will always use it as a benchmark. This method is called &#8220;Naïve&#8221;, and here is why it is popular and important. Naïve is a very simple forecasting method: the forecast equals to the last observed value. ... <a title="Why Naïve is popular and important" class="read-more" href="https://openforecast.org/2026/08/27/why-naive-is-popular-and-important/" aria-label="Read more about Why Naïve is popular and important">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/08/27/why-naive-is-popular-and-important/">Why Naïve is popular and important</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>There is one forecasting method that appears more often than any other in competitions and evaluations. An experienced forecaster will always use it as a benchmark. This method is called &#8220;Naïve&#8221;, and here is why it is popular and important.</p>
<p>Naïve is a very simple forecasting method: the forecast equals to the last observed value. So, for example, if the room temperature at 12pm was 20 degrees Celsius, then Naive will forecast exactly the same temperature for 1pm, and it will usually be roughly right. That is what makes it dangerous to sophisticated models: it is often surprisingly hard to beat. If your model cannot beat Naïve, it is not worth deploying, no matter how sophisticated and beautiful it is.</p>
<p>This is why there is a well-established rule in forecasting: any proper evaluation should include simple benchmarks, and Naïve is the easiest one to implement, because it does not have any parameters to estimate and can work with the sample of one observation. This is why you will find it in every decent forecasting competition.</p>
<p>This is not a new finding, by the way. Back in 1979, Spyros Makridakis and Michèle Hibon <a href="https://doi.org/10.2307/2345077">published a paper</a>, showing on a set of 111 real time series that simple methods were often at least as accurate as the sophisticated statistical ones. The audience did not take it well: the discussion that followed was openly hostile, with eminent statisticians suggesting that the results said more about the authors&#8217; skills than about the methods. Spyros&#8217; response was to test the claim at a much larger scale, which is how the M-competitions were born. <a href="/2024/03/14/the-role-of-m-competitions-in-forecasting/">I wrote a post</a> about that some time ago. But the lesson survived the criticism: always compare your approach with the simple forecasting methods.</p>
<p>In our training course on Demand Forecasting Principles, we discuss this and other simple methods in more detail, showing where they work and where they fail. They are all building blocks for understanding applied forecasting.</p>
<p>The next course runs online in October, over Zoom. <a href="https://openforecast.org/training/demand-forecasting-principles/">Details and booking can be found here</a>.</p>
<p>P.S. There is one case where Naïve is not a good benchmark, read <a href="/2024/12/02/why-naive-is-not-a-good-benchmark-for-intermittent-demand/">this post</a>.</p>
<p>Message <a href="https://openforecast.org/2026/08/27/why-naive-is-popular-and-important/">Why Naïve is popular and important</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/08/27/why-naive-is-popular-and-important/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>stick function for the EDA in time series</title>
		<link>https://openforecast.org/2026/06/26/stick-function-for-the-eda-in-time-series/</link>
					<comments>https://openforecast.org/2026/06/26/stick-function-for-the-eda-in-time-series/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Fri, 26 Jun 2026 11:24:43 +0000</pubDate>
				<category><![CDATA[Applied forecasting]]></category>
		<category><![CDATA[greybox in Python]]></category>
		<category><![CDATA[Package greybox for R]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[R]]></category>
		<category><![CDATA[time series]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4157</guid>

					<description><![CDATA[<p>You have probably seen my post about the STI classification of Hans Levenbach (this one). Well, I&#8217;ve decided to implement it, and it has landed in the greybox package for R/Python. What&#8217;s greybox? It is a package for statistical modelling focusing on forecasting and time series analysis. I created it back in 2018 to split ... <a title="stick function for the EDA in time series" class="read-more" href="https://openforecast.org/2026/06/26/stick-function-for-the-eda-in-time-series/" aria-label="Read more about stick function for the EDA in time series">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/06/26/stick-function-for-the-eda-in-time-series/">stick function for the EDA in time series</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>You have probably seen my post about the STI classification of Hans Levenbach (<a href="/2026/05/18/hans-levenbach-s-classification-scheme-for-trend-seasonal-components/">this one</a>). Well, I&#8217;ve decided to implement it, and it has landed in the greybox package for R/Python.</p>
<p>What&#8217;s greybox? It is a package for statistical modelling focusing on forecasting and time series analysis. I created it back in 2018 to split the static models (such as linear regression) from the dynamic ones that landed in the smooth package. Greybox has evolved since then, and now has linear regression (alm), regression selection (stepwise) and combinations (calm), a variety of tools for feature generation, diagnostics, forecast evaluation (e.g. rolling origin) etc. You can <a href="https://github.com/config-i1/greybox/wiki">read more about it here</a>. Originally, the package was available for R only, but Claude and I ported its main functions to Python back in February.</p>
<p>The Exploratory Data Analysis techniques for time series fit the package quite well, although I don&#8217;t have many of those yet. So, I&#8217;ve implemented the main idea of the STI of Hans Levenbach in a function called &#8220;stick&#8221; (Seasonal, Trend, Irregular Contribution Kit) in the greybox package for R/Python. The idea is straightforward: apply stick to a time series, it will use ANOVA, and give you the strength of each component. Here, for example, is how to apply the function to the AirPassengers data (everyone&#8217;s favourite toy time series) in R:</p>
<pre class="decode">library(greybox)
stick(AirPassengers)</pre>
<p>and in Python:</p>
<pre class="decode">from fcompdata import AirPassengers
from greybox import stick

result = stick(AirPassengers.y, lags=12)
print(result)</pre>
<p>which gives exactly the same result:</p>
<pre>Strength of the components:
seasonal12      trend  irregular
    0.1061     0.8613     0.0326</pre>
<p>So, trend dominates the time series, explaining 86.13% of its variability, meaning that if you capture it correctly, you solve a big chunk of the problem. This split also gives you a rough idea about the structure-versus-noise breakdown in the time series, although it assumes that the seasonal component does not evolve over time.</p>
<p>The function supports several seasonal components, and I might extend it to include external information (e.g. promotions) in the future if there is demand for it.</p>
<p>Message <a href="https://openforecast.org/2026/06/26/stick-function-for-the-eda-in-time-series/">stick function for the EDA in time series</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/06/26/stick-function-for-the-eda-in-time-series/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>smooth in python: Non-normal distributions in ETS/ARIMA</title>
		<link>https://openforecast.org/2026/05/27/smooth-in-python-non-normal-distributions-in-ets-arima/</link>
					<comments>https://openforecast.org/2026/05/27/smooth-in-python-non-normal-distributions-in-ets-arima/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Wed, 27 May 2026 14:17:46 +0000</pubDate>
				<category><![CDATA[ETS]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[smooth for Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[ADAM]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[smooth]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4152</guid>

					<description><![CDATA[<p>So, you know quite well that the normal distribution is one of the most popular distributions in statistics. The reasons are manifold, including convenience for the academic community and the fact that it is taught in every single statistics course in the world. But what if we don&#8217;t want to be normal? There are situations ... <a title="smooth in python: Non-normal distributions in ETS/ARIMA" class="read-more" href="https://openforecast.org/2026/05/27/smooth-in-python-non-normal-distributions-in-ets-arima/" aria-label="Read more about smooth in python: Non-normal distributions in ETS/ARIMA">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/05/27/smooth-in-python-non-normal-distributions-in-ets-arima/">smooth in python: Non-normal distributions in ETS/ARIMA</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>So, you know quite well that the normal distribution is one of the most popular distributions in statistics. The reasons are manifold, including convenience for the academic community and the fact that it is taught in every single statistics course in the world. But what if we don&#8217;t want to be normal?</p>
<p>There are situations where non-normal distributions fit considerably better. The main candidate for substitution is the conditional distribution of the response variable. For example, sales of engines cannot follow the normal distribution by definition: they are intermittent and integer-based — you cannot sell 1.78 engines. More generally, while demand can be fractional, it cannot be negative. It is therefore only logical to use distributions that support positive values only in these situation. Examples include Log-Normal, Gamma, and Inverse Gaussian, among many others.</p>
<p>In my last paper with John Boylan (<a href="/2024/01/10/staying-positive-challenges-and-solutions-in-using-pure-multiplicative-ets-models/">this one</a>), we discussed how ETS can be extended to use these three distributions instead of the normal one. I implemented this functionality (together with the others, such as Laplace and Generalised Normal) in ADAM. It supports any of these distributions with any ETS/ARIMA/regression model, for both additive and multiplicative error terms. There is some maths involved, which you can find <a href="https://openforecast.org/adam/ADAMETSAdditiveDistributions.html">here</a> and <a href="https://openforecast.org/adam/ADAMETSMultiplicativeDistributions.html">here</a>.</p>
<p>Why bother? The main is in the predictive distribution. If the data is not normal, we may end up with poorly calibrated forecasts and misleading prediction intervals. Using a more appropriate distribution can resolve this.</p>
<p>But how do we choose the right distribution for our data?</p>
<p>A possible solution (similar to selecting ETS components) is to fit models with different distributions and pick the one with the lowest information criterion. This is implemented in the ADAM function from the smooth package. We can do this manually, or use AutoADAM (called auto.adam in R) to select the most suitable distribution based on AICc automatically:</p>
<pre class="decode">from fcompdata import AirPassengers
from smooth import AutoADAM

model = AutoADAM(lags=[12], h=12, holdout=True, orders=None, verbose=True)
model.fit(AirPassengers.y)
model.summary()</pre>
<p>The <code>orders=None</code> line stops the function from trying different ARIMA orders &#8211; something we will come back to in a future post. For this example, the output is:</p>
<pre>Model estimated using ADAM() function: ETS(MAM)
Response variable: y
Distribution used in the estimation: Normal
Loss function type: likelihood; Loss function value: 523.2756
Coefficients:
       Estimate  Std. Error  Lower 2.5%  Upper 97.5%   
alpha    0.7575      0.0895      0.5807       0.9343  *
beta     0.0000      0.0080      0.0000       0.0158   
gamma    0.0000      0.0503      0.0000       0.0994   
Error standard deviation: 0.0358
Sample size: 144
Number of estimated parameters: 4
Number of degrees of freedom: 140
Information criteria:
      AIC     AICc       BIC      BICc
1054.5512 1054.839 1066.4305 1067.1455</pre>
<p>Boring&#8230; the function found that the Normal distribution has the lowest AICc among those tested &#8211; the Air Passengers data is too well-behaved.</p>
<p>Oh, and don&#8217;t forget to produce the forecasts:</p>
<pre class="decode">model.predict(h=18, interval="prediction")</pre>
<p>Smooth forecasting!</p>
<p>Install smooth: <code>pip install smooth</code></p>
<p>Message <a href="https://openforecast.org/2026/05/27/smooth-in-python-non-normal-distributions-in-ets-arima/">smooth in python: Non-normal distributions in ETS/ARIMA</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/05/27/smooth-in-python-non-normal-distributions-in-ets-arima/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 fetchpriority="high" 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 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="(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>smooth in python: multiple seasonal ETS</title>
		<link>https://openforecast.org/2026/05/11/smooth-in-python-multiple-seasonal-ets/</link>
					<comments>https://openforecast.org/2026/05/11/smooth-in-python-multiple-seasonal-ets/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 11 May 2026 08:08:38 +0000</pubDate>
				<category><![CDATA[ETS]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[smooth for Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[smooth]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4140</guid>

					<description><![CDATA[<p>Another interesting case in demand forecasting is the high frequency data. For example, if you work with demand on daily level, you might notice that demand increases every Monday but also exhibits proper seasonal fluctuations (e.g. decline every Winter). What do you do in this case? One of the solutions (old but gold) is the ... <a title="smooth in python: multiple seasonal ETS" class="read-more" href="https://openforecast.org/2026/05/11/smooth-in-python-multiple-seasonal-ets/" aria-label="Read more about smooth in python: multiple seasonal ETS">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/05/11/smooth-in-python-multiple-seasonal-ets/">smooth in python: multiple seasonal ETS</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Another interesting case in demand forecasting is the high frequency data. For example, if you work with demand on daily level, you might notice that demand increases every Monday but also exhibits proper seasonal fluctuations (e.g. decline every Winter). What do you do in this case?</p>
<p>One of the solutions (old but gold) is the multiple seasonal ETS model, which was originally developed by James Taylor (<a href="https://doi.org/10.1057/palgrave.jors.2601589">2003</a>) for the pure additive exponential smoothing. The idea was quite simple: to model multiple seasonal cycles, one can add multiple seasonal components, i.e. to capture the day-of-week (frequency 7) and the day-of-year (frequency 365) effects. While it worked fine for some examples, the main issue with it has been its computational speed (or rather slowness): the original ETS needs to estimate all smoothing parameters + all the initial values for seasonal indices and other components. Both ADAM and ES in the smooth package support multiple seasonalities and avoid the whole issue by using a different model initialisation called &#8220;backcasting&#8221;.</p>
<p>Here is a classical example from James&#8217; paper on the half-hourly electricity demand (see the image in the post). It is clear that there is a half-hour-of-day and the day-of-week effects. In ES, this means that we need to provide the vector for the lags variable:</p>
<pre class="decode">from smooth import ES
from fcompdata import taylor

# Fit ES with automatic ETS model selection
model = ES(lags=[48, 336], h=336, holdout=True)
model.fit(taylor.y)
model.predict(h=336)
print(model)</pre>
<p>This is the output I get from the function:</p>
<pre>Time elapsed: 2.03 seconds
Model estimated using ES() function: ETS(MNM)
With backcasting initialisation
Distribution assumed in the model: Normal
Loss function type: likelihood; Loss function value: 25391.1773
Persistence vector g:
 alpha gamma1 gamma2
0.2899 0.1283 0.5270
Sample size: 3696
Number of estimated parameters: 4
Number of degrees of freedom: 3692
Information criteria:
      AIC      AICc       BIC      BICc
50790.3546 50790.3654 50815.2146 50815.2591

Forecast errors:
ME: 829.1195; MAE: 942.1447; RMSE: 1065.1127
sCE: 941.5012%; Asymmetry: 9.2%; sMAE: 3.1841%; sMSE: 0.1296%
MASE: 1.4491; RMSSE: 1.1286; rMAE: 0.1408; rRMSE: 0.1300</pre>
<p>The computational time on this data was only 2.03 second. In this time, the function tried several possible ETS models and selected the best one based on the AICc value. The resulting best model is ETS(M,N,M), which makes perfect sense for this data.</p>
<p>Is there a way to improve this model? Yes! Taylor mentions that adding AR(1) to the cocktail tends to improve the accuracy in case of multiple seasonal series. We can try that if we switch to ADAM:</p>
<pre class="decode">from smooth import ADAM

# Fit ADAM ETS(MNM)+AR(1) model
model = ADAM(model="MNM", ar_orders=1, lags=[48, 336], h=336, holdout=True)
model.fit(taylor.y)
print(model)
model.plot(7)</pre>
<p>Here is the output:</p>
<pre>Time elapsed: 1.04 seconds
Model estimated using ADAM() function: ETS(MNM)+ARIMA(1,0,0)
With backcasting initialisation
Distribution assumed in the model: Gamma
Loss function type: likelihood; Loss function value: 24157.2473
Persistence vector g:
 alpha gamma1 gamma2
0.1097 0.2225 0.3481
ARMA parameters of the model:
             Lag 1
AR(1)       0.6852
Sample size: 3696
Number of estimated parameters: 5
Number of degrees of freedom: 3691
Information criteria:
      AIC      AICc       BIC      BICc
48324.4947 48324.5109 48355.5697 48355.6365

Forecast errors:
ME: 276.4061; MAE: 462.5092; RMSE: 588.5957
sCE: 313.8711%; Asymmetry: 2.1%; sMAE: 1.5631%; sMSE: 0.0396%
MASE: 0.7114; RMSSE: 0.6237; rMAE: 0.0691; rRMSE: 0.0719</pre>
<p>The resulting model has lower AICc, but also produces more accurate point forecasts (compare RMSSE values) for the holdout set. The following image shows the data and the point forecasts for it:</p>
<figure id="attachment_4142" aria-describedby="caption-attachment-4142" 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-04-17-smooth-posts-04-Multiple-seasonal-ETS-02.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-04-17-smooth-posts-04-Multiple-seasonal-ETS-02-300x214.png&amp;nocache=1" alt="Double seasonal ETS(M,N,M) applied to the half-hourly electricity demand data" width="300" height="214" class="size-medium wp-image-4142" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-04-Multiple-seasonal-ETS-02-300x214.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-04-Multiple-seasonal-ETS-02.png&amp;nocache=1 700w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-4142" class="wp-caption-text">Double seasonal ETS(M,N,M) applied to the half-hourly electricity demand data</figcaption></figure>
<p>What else can we do here? Actually, quite a lot: multistep losses, seasonal ARIMA, explanatory variables &#8211; things can get only more complicated from here. Have a look <a href="https://openforecast.org/adam/ADAMMultipleFrequenciesExamples.html">at this</a>.</p>
<p>Do I hear someone shouting &#8220;TBATS&#8221;? TBATS is the exponential smoothing with additional bells and whistles (ETS + adapted Fourier terms + ARMA errors). I don&#8217;t have it as a separate function in the smooth just yet, but you can reproduce it, for example, <a href="https://openforecast.org/adam/ETSXMultipleSeasonality.html">like this</a>.</p>
<p>So, what are you waiting for? Dive in and see how it works for yourself!</p>
<p>Install smooth: pip install smooth</p>
<p>Message <a href="https://openforecast.org/2026/05/11/smooth-in-python-multiple-seasonal-ets/">smooth in python: multiple seasonal ETS</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/05/11/smooth-in-python-multiple-seasonal-ets/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>smooth in python: ETS with explanatory variables</title>
		<link>https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/</link>
					<comments>https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Tue, 05 May 2026 08:03:37 +0000</pubDate>
				<category><![CDATA[ETS]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[smooth for Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[smooth]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4128</guid>

					<description><![CDATA[<p>We continue our series of posts on the functions from the smooth package for Python/R. Today we will see how to enhance your exponential smoothing with explanatory variables. What? Yes, you heard me! Let&#8217;s dive in! We all know that in real life sales don&#8217;t just evolve over time on their own. Any univariate model, ... <a title="smooth in python: ETS with explanatory variables" class="read-more" href="https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/" aria-label="Read more about smooth in python: ETS with explanatory variables">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/">smooth in python: ETS with explanatory variables</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>We continue our series of posts on the functions from the smooth package for Python/R. Today we will see how to enhance your exponential smoothing with explanatory variables. What? Yes, you heard me! Let&#8217;s dive in!</p>
<p>We all know that in real life sales don&#8217;t just evolve over time on their own. Any univariate model, such as ARIMA or ETS is just a way to approximate a complex reality. In practice, there are many factors affecting the demand for your product. What would happen if the price on your product increases? What if you run a promotion (e.g. &#8220;Buy One, Get One Free&#8221;)? Your competitor&#8217;s strategy impacts the demand for your product as well&#8230; There&#8217;s lots of different factors, and some of them can be quite useful in demand forecasting. But can we join the dynamic univariate models with regression?</p>
<p>Yes, we can! Although ETS is thought as a pure univariate model, it is easy to extend to include explanatory variables. There are several great papers showing how it works (e.g. <a href="https://doi.org/10.1016/j.ijpe.2015.09.011">Kourentzes &#038; Petropoulos, 2016</a>), and in fact the <code>es()</code> function from the smooth package for R was used as a benchmark in <a href="https://doi.org/10.1016/j.ijforecast.2021.11.013">the M5 competition</a>.</p>
<p>So, consider a situation where you have weekly sales of a product with some recorded promotions (encoded as dummy variables). We will use a time series from the fcompdata package for Python. The first image shows how the series looks, the vertical lines show when promotions happen. The series itself seems to be seasonal, roughly repeating peaks and troughs every 52 observations (every year). Also, we see that there are two types of promotions, and when they happen sales tend to increase. So, including them should improve the model fit, and if the company decides to run promotions again, the model will forecast demand better. I will start by fitting the ETS(M,N,M) to the data:</p>
<pre class="decode">from smooth import ES
from fcompdata import PromoData

y = PromoData.y

model = ES(model="MNM", lags=52, holdout=True, h=13)
model.fit(y)
model.predict(h=13)
model.plot(7)</pre>
<p><strong>NOTE</strong>: PromoData has a specific structure with several attributes. PromoData.x contains the in-sample data, PromoData.xx has the holdout &#8211; this is consistent with the Mcomp package for R. The new features in python are:</p>
<ul>
<li>PromoData.y &#8211; concatenated training and test sets,</li>
<li>PromoData.xregx &#8211; matrix of explanatory variables for the training set,</li>
<li>PromoData.xregxx &#8211; matrix of explanatory variables for the test set,</li>
<li>PromoData.xreg &#8211; the full (concatenated) matrix of explanatory variables.</li>
</ul>
<p>The following image shows the model fit and the point forecasts from the ETS(M,N,M):</p>
<figure id="attachment_4132" aria-describedby="caption-attachment-4132" 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-04-17-smooth-posts-03-ETSX-02.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-04-17-smooth-posts-03-ETSX-02-300x214.png&amp;nocache=1" alt="ETS(M,N,M) fit and forecast for the promotional data example" width="300" height="214" class="size-medium wp-image-4132" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-02-300x214.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-02.png&amp;nocache=1 700w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-4132" class="wp-caption-text">ETS(M,N,M) fit and forecast for the promotional data example</figcaption></figure>
<p>As expected, because the model does not take promotions into account, it fits the data as best as it can and produces forecasts that are oblivious of the potential external effects on sales. We can improve it by including the promotional dummies:</p>
<pre class="decode">X_train = PromoData.xreg
X_test =  PromoData.xregxx

model = ES(model="MNM", lags=52, holdout=True, h=13)
model.fit(y, X_train)
model.predict(h=13, X=X_test)
model.plot(7)</pre>
<figure id="attachment_4131" aria-describedby="caption-attachment-4131" 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-04-17-smooth-posts-03-ETSX-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-04-17-smooth-posts-03-ETSX-03-300x214.png&amp;nocache=1" alt="ETS(M,N,M) with explanatory variables" width="300" height="214" class="size-medium wp-image-4131" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-03-300x214.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-03.png&amp;nocache=1 700w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-4131" class="wp-caption-text">ETS(M,N,M) with explanatory variables</figcaption></figure>
<p>The image above shows the fit and the point forecasts from the ETSX(M,N,M) model that now takes the promotions into account. This is quite an improvement in comparison with the previous one. Furthermore, if we can control when to have promotions and what types of promotions to run, we can change the values in the `X_test` matrix and see what demand to expected in that situation. So, this gives an analyst a tool for a more advanced sensitivity analysis.</p>
<p>Read more about the ETSX <a href="https://openforecast.org/adam/ADAMX.html">here</a>.<br />
Install smooth: <code>pip install smooth</code><br />
<a href="https://github.com/config-i1/smooth/wiki/Explanatory-Variables">ETSX wiki on github</a>.</p>
<p>Message <a href="https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/">smooth in python: ETS with explanatory variables</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>smooth in python: ETS with model selection</title>
		<link>https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/</link>
					<comments>https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 00:06:43 +0000</pubDate>
				<category><![CDATA[ETS]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[smooth for Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[ADAM]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[smooth]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4111</guid>

					<description><![CDATA[<p>As some of you have heard, the smooth package is now on PyPI. So, I&#8217;ve decided to write a series of posts showcasing how some of its functions work. We start with the basics, ETS. ETS stands for the &#8220;Error-Trend-Seasonal&#8221; model or ExponenTial Smoothing. It is a statistical model that relies on time series decomposition ... <a title="smooth in python: ETS with model selection" class="read-more" href="https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/" aria-label="Read more about smooth in python: ETS with model selection">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/">smooth in python: ETS with model selection</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>As some of you have heard, the smooth package is now on PyPI. So, I&#8217;ve decided to write a series of posts showcasing how some of its functions work. We start with the basics, ETS.</p>
<p>ETS stands for the &#8220;Error-Trend-Seasonal&#8221; model or ExponenTial Smoothing. It is a statistical model that relies on time series decomposition and updates the unobserved states (level/trend/seasonal) based on the mistakes it makes. In a way, you can call it an adaptive model that changes its forecast based on the most recent available information. It is relatively simple to explain and work with, and it has performed well in a variety of competitions (M3, M4, M5, for example).</p>
<p>The smooth package implements an advanced form of ETS in the ADAM and a more basic one in the ES classes. In fact, ES is just a wrapper of ADAM, it is the conventional model, with just some tuning. Both support all 30 ETS models, have automated model selection and forecast combination, allow producing point forecasts and a variety of prediction intervals types. In fact, if you want a straightforward robust implementation of ETS, give ES a try.</p>
<p>Here&#8217;s how to use it in Python:</p>
<pre class="decode">from smooth import ES
from fcompdata import M3

# Pick a series from the M3 competition for demonstration
series = M3[2568]
y = series.x
freq = series.period

# Fit ES with the automatic model selection
model = ES(lags=freq, h=18, holdout=True)
model.fit(y)
print(model)</pre>
<p>Running this produces output similar to this:</p>
<pre>Time elapsed: 0.4 seconds
Model estimated using ES() function: ETS(MAM)
With backcasting initialisation
Distribution assumed in the model: Normal
Loss function type: likelihood; Loss function value: 724.8524
Persistence vector g:
 alpha   beta  gamma
0.0065 0.0000 0.0000
Sample size: 98
Number of estimated parameters: 4
Number of degrees of freedom: 94
Information criteria:
      AIC      AICc       BIC      BICc
1457.7047 1458.1348 1468.0446 1469.0306

Forecast errors:
ME: -580.9985; MAE: 604.0204; RMSE: 710.5457
sCE: -149.9347%; Asymmetry: -2.5%; sMAE: 8.6598%; sMSE: 1.0378%
MASE: 0.2653; RMSSE: 0.2452; rMAE: 0.2555; rRMSE: 0.2163</pre>
<p>A few things worth noting from the output:</p>
<ul>
<li>ES automatically selected ETS(MAM) based on the AICc value &#8211; a multiplicative error, additive trend, multiplicative seasonality model &#8211; as the best fit</li>
<li>It used backcasting for the model initialisation (default), which speeds up the process and requires fewer parameters to estimate</li>
<li>It kept the last 18 observation for the holdout, produced autoforecasts for it and calculated several forecast errors. This is handy if you want to directly compare different smooth models on a time series.</li>
</ul>
<p>But why are we here? We want to forecast! So, here it is:</p>
<pre class="decode">
model.predict(h=18, interval="prediction")
model.plot(7)
</pre>
<p>This should produce an image similar to the one attached to the post. As simple as that.</p>
<p>Now it&#8217;s your turn! :)</p>
<p>🔗 Install smooth: pip install smooth<br />
📖 <a href="https://github.com/config-i1/smooth/wiki">smooth wiki</a></p>
<p>Message <a href="https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/">smooth in python: ETS with model selection</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The real Dunning-Kruger effect</title>
		<link>https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/</link>
					<comments>https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 23 Mar 2026 09:03:35 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4096</guid>

					<description><![CDATA[<p>Many of you have seen this image on the Internet — I&#8217;ve seen it myself a few times on LinkedIn lately. People say it depicts the &#8220;Dunning-Kruger&#8221; effect&#8230; But did you know this is actually an internet meme with little to do with the original paper? Here is one of the recent examples, a screenshot ... <a title="The real Dunning-Kruger effect" class="read-more" href="https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/" aria-label="Read more about The real Dunning-Kruger effect">Read more</a></p>
<p>Message <a href="https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/">The real Dunning-Kruger effect</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Many of you have seen this image on the Internet — I&#8217;ve seen it myself a few times on LinkedIn lately. People say it depicts the &#8220;Dunning-Kruger&#8221; effect&#8230; But did you know this is actually an internet meme with little to do with the original paper?</p>
<p>Here is one of the recent examples, a screenshot of <a href="https://www.linkedin.com/posts/fotios-petropoulos-04536023_dear-mr-i-reduce-forecast-error-by-30-share-7437246645530140672-NXnT">the post of Fotios Petropoulos</a> about the effect.</p>
<figure id="attachment_4098" aria-describedby="caption-attachment-4098" style="width: 262px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-Petropoulos.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/03/2026-03-22-Dunning-Kruger-Petropoulos-272x300.png&amp;nocache=1" alt="A LinkedIn post by Fotios Petropoulos" width="272" height="300" class="size-medium wp-image-4098" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-Petropoulos-272x300.png&amp;nocache=1 272w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-Petropoulos.png&amp;nocache=1 556w" sizes="auto, (max-width: 272px) 100vw, 272px" /></a><figcaption id="caption-attachment-4098" class="wp-caption-text">A LinkedIn post by Fotios Petropoulos</figcaption></figure>
<p>In the original paper, <a href="https://psycnet.apa.org/doi/10.1037/0022-3514.77.6.1121">Kruger and Dunning (1999)</a> ran experiments with undergraduates on humour, logical reasoning, and grammar. Participants completed a test and estimated their percentile rank. The authors then sorted participants into four quartiles by actual performance and computed averages for actual and self-assessed performance for each quartile. The plots in their paper &#8211; the real Dunning–Kruger effect &#8211; are just four data points per line, not a smooth curve over a learning journey (second image).</p>
<p>What did they find? People in the bottom quartile substantially overestimated their performance, often believing they were average or above. Top performers slightly underestimated their standing. The key finding is an asymmetry in miscalibration: low performers overestimate, high performers slightly underestimate.</p>
<p>This has almost nothing to do with the popular &#8220;experience vs. confidence&#8221; image. The original X‑axis is performance quartile at a single point in time; the meme&#8217;s X‑axis is a vague notion of &#8220;experience&#8221; through time. The original Y‑axis is the assessed test percentile; the meme&#8217;s is a free‑floating &#8220;confidence&#8221; construct. In the actual data, perceived performance increases with actual performance &#8211; there is no early spike, no &#8220;valley of despair,&#8221; no &#8220;slope of enlightenment.&#8221; That swooping curve is an internet-era graphic never reported by Kruger and Dunning, and it misleadingly frames the effect as a personal development trajectory the paper never studied.</p>
<p>There is also a serious critique of the original paper from statistical point of view. For example, <a href="https://doi.org/10.1016/j.intell.2020.101449">Gignac and Zajenkowski (2020)</a> showed that sorting people into quartiles and plotting average self-assessment against average performance can, by itself, generate the characteristic pattern &#8211; purely as a statistical artefact. In their own empirical data, miscalibration was roughly constant across ability levels, consistent with measurement noise rather than a special cognitive deficit in low performers. You can actually reproduce the pattern using two random uncorrelated variables. Here is a simple example in R:</p>
<pre class="decode">set.seed(41)

x <- rnorm(10000, 100, 10)
y <- rnorm(10000, 100, 10)
plot(x,y)
xQ <- quantile(x)
yQ <- quantile(y)

yMeans <- xMeans <- vector("numeric",4)

for(i in 1:4){
    xMeans[i] <- mean(x[x<xQ[i+1] &#038; x>xQ[i]])
    yMeans[i] <- mean(y[x<xQ[i+1] &#038; x>xQ[i]])
}

plot(1:4, xMeans, type="b", ylim=range(xMeans,yMeans),
     xlab="Real performance", ylab="Assessed performance",
     lwd=2)
lines(yMeans, lwd=2, lty=2)
points(yMeans, lwd=2)
legend("topleft",
       legend=c("Actual performance", "Assessed performance"),
       lwd=2, lty=c(1,2), pch=1)</pre>
<p>Which produces the image like this:</p>
<figure id="attachment_4100" aria-describedby="caption-attachment-4100" 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/03/2026-03-22-Dunning-Kruger-R.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/03/2026-03-22-Dunning-Kruger-R-300x175.png&amp;nocache=1" alt="Dunning-Kruger plot reproduction" width="300" height="175" class="size-medium wp-image-4100" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R-300x175.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R-1024x597.png&amp;nocache=1 1024w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R-768x448.png&amp;nocache=1 768w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R.png&amp;nocache=1 1200w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-4100" class="wp-caption-text">Dunning-Kruger plot reproduction</figcaption></figure>
<p>If you introduce a correlation between the two variables, the images starts looking even more similar to the ones from the original paper.</p>
<p>So there might be a real effect &#8211; many follow-up studies have measured it with more rigorous tools &#8211; but Dunning and Kruger&#8217;s method was not the right one to establish it. And that image with experience vs confidence is just a meme and a serious misconception that should not be used.</p>
<p>P.S. If you wonder who the &#8220;leading expert&#8221; that Fotios Petropoulos refers to in his post is &#8211; it&#8217;s me. Not sure why he doesn&#8217;t tag me properly.</p>
<p>Message <a href="https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/">The real Dunning-Kruger effect</a> first appeared on <a href="https://openforecast.org">OpenForecast</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
