<?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 - Open Forecasting</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>Wed, 27 May 2026 14:17:46 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2015/08/cropped-usd-05-32x32.png&amp;nocache=1</url>
	<title>Archives Social media - Open Forecasting</title>
	<link>https://openforecast.org/category/social-media/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<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 [&#8230;]</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">Open Forecasting</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">Open Forecasting</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. [&#8230;]</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">Open Forecasting</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>
<div id="attachment_4147" style="width: 310px" 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" aria-describedby="caption-attachment-4147" 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><p id="caption-attachment-4147" class="wp-caption-text">Series N2568 from the M3 dataset</p></div>
<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>
<div id="attachment_4149" style="width: 310px" 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" aria-describedby="caption-attachment-4149" 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><p id="caption-attachment-4149" class="wp-caption-text">Seasonal profile of the data</p></div>
<div id="attachment_4148" style="width: 310px" 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" aria-describedby="caption-attachment-4148" 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><p id="caption-attachment-4148" class="wp-caption-text">Trend profile</p></div>
<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">Open Forecasting</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 [&#8230;]</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">Open Forecasting</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>
<div id="attachment_4142" style="width: 310px" 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" aria-describedby="caption-attachment-4142" 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><p id="caption-attachment-4142" class="wp-caption-text">Double seasonal ETS(M,N,M) applied to the half-hourly electricity demand data</p></div>
<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">Open Forecasting</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, [&#8230;]</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">Open Forecasting</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>
<div id="attachment_4132" style="width: 310px" 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" aria-describedby="caption-attachment-4132" 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><p id="caption-attachment-4132" class="wp-caption-text">ETS(M,N,M) fit and forecast for the promotional data example</p></div>
<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>
<div id="attachment_4131" style="width: 310px" 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" aria-describedby="caption-attachment-4131" 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><p id="caption-attachment-4131" class="wp-caption-text">ETS(M,N,M) with explanatory variables</p></div>
<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">Open Forecasting</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 [&#8230;]</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">Open Forecasting</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">Open Forecasting</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 [&#8230;]</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">Open Forecasting</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>
<div id="attachment_4098" style="width: 282px" 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" aria-describedby="caption-attachment-4098" 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><p id="caption-attachment-4098" class="wp-caption-text">A LinkedIn post by Fotios Petropoulos</p></div>
<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>
<div id="attachment_4100" style="width: 310px" 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" aria-describedby="caption-attachment-4100" 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><p id="caption-attachment-4100" class="wp-caption-text">Dunning-Kruger plot reproduction</p></div>
<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">Open Forecasting</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>
		<item>
		<title>There&#8217;s no such thing as &#8220;deterministic forecast&#8221;</title>
		<link>https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/</link>
					<comments>https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 02 Mar 2026 22:45:31 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4081</guid>

					<description><![CDATA[<p>Sometimes I see people referring to a &#8220;deterministic&#8221; forecast, and I have some personal issues with this. Because if you apply a model to data then there is nothing deterministic about your forecasts! In many contexts, &#8220;deterministic&#8221; has a precise meaning: no randomness, no uncertainty. A deterministic solution to an optimisation problem (e.g. linear programming) [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/">There&#8217;s no such thing as &#8220;deterministic forecast&#8221;</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Sometimes I see people referring to a &#8220;deterministic&#8221; forecast, and I have some personal issues with this. Because if you apply a model to data then there is nothing deterministic about your forecasts!</p>
<p>In many contexts, &#8220;deterministic&#8221; has a precise meaning: no randomness, no uncertainty. A deterministic solution to an optimisation problem (e.g. linear programming) implies that there are no random inputs or outputs once the model and its parameters are fixed. Forecasting is different. As <a href="https://onlinelibrary.wiley.com/doi/10.1002/(SICI)1099-131X(199612)15:7%3C495::AID-FOR640%3E3.0.CO;2-O">Chatfield</a> and many others have pointed out, forecasting has multiple sources of uncertainty, and there is essentially zero chance that the future will unfold exactly as any single number suggests.</p>
<p>Yes, some people use &#8220;deterministic&#8221; as a synonym for &#8220;point forecast&#8221;. But that label is still misleading, because a point forecast is not uncertainty-free &#8211; it is just one summary of a predictive distribution (often the conditional mean, sometimes the median or another functional).</p>
<p>Here’s a quick reality check you can do yourself. Take a dataset, apply your model, and write down the point forecast for the next few observations. Now add one new observation, re-estimate, and forecast again (the image in this post depicts exactly that, but with 50 forecasts produced on different subsamples of data). The point forecast will change unless you are dealing with an exotic situation with non-random data (e.g. every day, you sell exactly 100 units). So, which of the two was the &#8220;deterministic&#8221; forecast? If forecasts were truly deterministic in the strict sense, you would not get multiple plausible values from small, reasonable changes in the sample.</p>
<p>This happens because any forecasting method (statistical or ML) depends on data and on modelling choices: parameter estimation, feature selection, splitting rules, tuning, even decisions like &#8220;use α=0.1&#8221;. Those choices can be fixed across samples of data, but fixing them does not remove uncertainty &#8211; it only hides it. The randomness is still there in the data and in the fact that we only observe a sample of it.</p>
<p>So when you see someone mentioning &#8220;deterministic forecast&#8221;, it&#8217;s worth translating it mentally to: &#8220;a point forecast, probably a conditional mean&#8221;. If you care about decisions and risk, you should know that there is an uncertainty associated with this so called &#8220;deterministic forecast&#8221;, and that it should not be ignored. But this is a topic for another discussion in another post.</p>
<p>Message <a href="https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/">There&#8217;s no such thing as &#8220;deterministic forecast&#8221;</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Scaling of error measures</title>
		<link>https://openforecast.org/2026/02/23/scaling-of-error-measures/</link>
					<comments>https://openforecast.org/2026/02/23/scaling-of-error-measures/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 23 Feb 2026 13:36:12 +0000</pubDate>
				<category><![CDATA[Forecast evaluation]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[error measures]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4054</guid>

					<description><![CDATA[<p>Apparently, we need to talk about scaling of error measures because this is not as obvious as it seems. In forecasting literature, since early days of the area, there has been a general consensus that the forecast errors from the individual time series should not be analysed and aggregated as is. This is because you [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/02/23/scaling-of-error-measures/">Scaling of error measures</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Apparently, we need to talk about scaling of error measures because this is not as obvious as it seems.</p>
<p>In forecasting literature, since early days of the area, there has been a general consensus that the forecast errors from the individual time series should not be analysed and aggregated as is. This is because you can have very different time series capturing dynamics of very different processes.</p>
<p>Indeed, if you forecast sales of apples in kilograms, your actual value would be apples in kilograms, and your point forecast would also be in the same units. Subtracting one from another tells us how many kilograms of apples we missed with the forecast we produced. But if we then take the average between forecast errors for apples and beer, we would be aggregating things in different units, which contradicts some basic aggregating principles.</p>
<p>Furthermore, if the company sells thousands of kilograms of apples and jet engines, aggregating forecast errors on those (e.g. 3000 vs 3) might introduce all types of issues, because the models performance on apples might mask the performance of the model on jet engines. Still, the jet engines are much more expensive than apples and getting them accurately might be more important for the company than forecasting apples.</p>
<p>So, forecasting literature has agreed that the forecast errors need to be somehow scaled to make the errors unitless and not to distort performance of models on time series with different volumes. There are several ways of doing that, including the poor ones and reasonable ones. The state of the art at the moment is to divide error measures by some in-sample statistics to avoid potential holdout-sample distortion. Using mean absolute differences (MAD) for this (thus ending up with MASE or RMSSE) is considered as a standard. A couple of years ago, <a href="/2019/08/25/are-you-sure-youre-precise-measuring-accuracy-of-point-forecasts/">I have written a post about advantages and disadvantages of several scaling methods</a>.</p>
<p>But there is one method that I haven&#8217;t looked at and which is not very well discussed in the forecasting literature. It relies on the monetary value of forecasts. We could multiply each individual forecast error &#8220;e&#8221; by the price of the product &#8220;p&#8221; (thus moving to the missed income per product) and then divide everything by the overall income (price times quantity) from different products. This can be written as:</p>
<p>\begin{equation}<br />
\text{monetary Mean Error} = \frac{\sum_{j=1}^n (p_j \times e_j)} {\sum_{j=1}^n (p_j \times q_j)}<br />
\end{equation}</p>
<p>(the above formula can be modified to have squares or absolute values of the error). This way we switch from the original units to the monetary values and each error would tell you the percentage of the missed income in the overall one. This is a useful measure because it connects models performance with some managerial decisions and it takes the value of product into account (thus we do not mask the expensive jet engines with cheap apples).</p>
<p>However, it might have a potential issue similar to what the MAE/Mean or wMAPE has: if the sales of the product are not stationary, the denominator would change, thus driving the proportion either up or down, irrespective of how good the forecast is. I am not sure whether this needs to be addressed, because there is an argument that if the income from a product has increased and the error hasn&#8217;t changed, then this means that the proportion of the missed income decreased, which makes sense. But if we need to address this, we can switch to the MAD multiplied by price in the denominator to address this issue. In fact, this was sort of done in <a href="https://doi.org/10.1016/j.ijforecast.2021.11.013">M5 competition</a> that used a weighted RMSSE, relying on the income from each product over the last 4 weeks of data.</p>
<p>But here is one more interesting thing about this error measure. If we <strong>assume that prices for all products are exactly the same</strong>, they will disappear from the numerator and the denominator, leaving us with just sum of errors divided by the overall sales of all products. This still maintains the original idea of the proportion of the missed income, but now has a very strong assumption, which is probably not correct in the real life (apples and engines for the same price?). Furthermore, this would mask the performance of the model for the expensive products again. I personally don&#8217;t like this measure and find the assumption unrealistic and potentially misleading. Having said that, I can see some cases where this could still be acceptable and useful (e.g. similar products with similar dynamics and similar prices).</p>
<p>Summarising:</p>
<ol>
<li>If you are conducting a forecasting experiment without a specific context, I&#8217;d recommend using RMSSE or some other similar measure with scaling.</li>
<li>If you have prices of products, income-based scaling might be more informative.</li>
<li>Setting all prices to the same value does not sound appealing to me, but I understand that there is a context where this might work.</li>
</ol>
<p>Message <a href="https://openforecast.org/2026/02/23/scaling-of-error-measures/">Scaling of error measures</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/02/23/scaling-of-error-measures/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Forecasting Competitions Datasets in Python</title>
		<link>https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/</link>
					<comments>https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 26 Jan 2026 09:29:25 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Competitions]]></category>
		<category><![CDATA[time series]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3955</guid>

					<description><![CDATA[<p>Here is one small, unexpected piece of news: I now have my first package on PyPI! It’s called fcompdata, and let me tell you a little bit about it. When I test my functions in R, I usually use the M1, M3, and tourism competition datasets because they are diverse enough, containing seasonal, non-seasonal, trended, [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/">Forecasting Competitions Datasets in Python</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Here is one small, unexpected piece of news: I now have my first package on PyPI! It’s called <a href="https://pypi.org/project/fcompdata/">fcompdata</a>, and let me tell you a little bit about it.</p>
<p>When I test my functions in R, I usually use the M1, M3, and tourism competition datasets because they are diverse enough, containing seasonal, non-seasonal, trended, and non-trended time series of different frequencies (yearly, quarterly, monthly). The total number of these series is 5,315, which is large enough but not too heavy for my PC. So, when I run something on those datasets, it becomes like a stress test for the forecasting approach, and I can see where it fails and how it can be improved. I consider this type of test a toy experiment — something to do before applying anything to real-world data.</p>
<p>In R, there are the Mcomp and Tcomp packages that contain these datasets, and I like how they are organised. You can do something like this:</p>
<pre class="decode">series <- Mcomp::M3[[2568]]
ourModel <- adam(series$x)
ourForecast <- forecast(model, h=series$h)
ourError <- series$xx - ourForecast$mean</pre>
<p>Each series from the dataset contains all the necessary attributes to run the experiment without trouble. This is easy and straightforward. Plus, I don’t need to download or organise any data — I just use the installed package.</p>
<p>When I started vibe coding in Python, I realised that I missed this functionality. So, with the help of Claude AI, I created a Python script to download the data from the Monash repository and organise it the way I liked. But then I realised two things, which motivated me to package it:</p>
<ol>
<li>I needed to drag this script with me to every project I worked on. It would be much easier to just run "pip install fcompdata" and forget about everything else.</li>
<li>Some series in the Monash repository differ from those in the R package.</li>
</ol>
<p>Wait, what?! Really?</p>
<p>Yes. The difference is tiny — it’s a matter of rounding. For example, series N350 from the M1 competition data (T169 from the quarterly data subset) has three digits in the R package and only two if downloaded from the Monash repository (Zenodo website).</p>
<p>Who cares?! It's just one digit difference, right?</p>
<p>Well, if you want to reproduce results across different languages, this tiny difference might become your nightmare. So, I care (and probably nobody else in the world), and I decided to create a proper Python package. You can now do this in Python and relax:</p>
<pre class="decode">pip install fcompdata

from fcompdata import M1, M3, Tourism
series = M3[2568]</pre>
<p>The "series" object is now an instance of the MCompSeries class that has the same attributes as in R: series.x, series.h, series.xx, etc.</p>
<p>As simple as that!</p>
<p>One more thing: I’ve added support for the M4 competition data, which — when imported — will be downloaded and formatted properly. The dataset is large (100k time series), and I personally don’t like it. I even wrote <a href="https://openforecast.org/2020/03/01/m-competitions-from-m4-to-m5-reservations-and-expectations/">a post about it back in 2020</a>. But if I want the package to be useful to a wider audience, I shouldn’t impose my personal preferences — you should decide for yourselves whether to use it or not.</p>
<p>P.S. Submitting to PyPI gave me a good understanding of the submission process for Python and why it can be such a mess. My package was published just a few seconds after submission — nobody looked at it, nobody ran any tests. CRAN does a variety of checks to ensure you don’t submit garbage. PyPI doesn’t care. So, I’ve gained more respect for CRAN after submitting this package to PyPI.</p>
<p>Message <a href="https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/">Forecasting Competitions Datasets in Python</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Risky business: how to select your model based on risk preferences</title>
		<link>https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/</link>
					<comments>https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 19 Jan 2026 11:28:04 +0000</pubDate>
				<category><![CDATA[Applied forecasting]]></category>
		<category><![CDATA[Papers]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[error measures]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[Information criteria]]></category>
		<category><![CDATA[model combination]]></category>
		<category><![CDATA[model selection]]></category>
		<category><![CDATA[papers]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3950</guid>

					<description><![CDATA[<p>What do you use for model selection? Do you select the best model based on its cross-validated performance, or do you use in-sample measures like AIC? If so, there is a way to improve your selection process further. JORS recently published the paper of Nikos Kourentzes and I based on a simple but powerful idea: [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/">Risky business: how to select your model based on risk preferences</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>What do you use for model selection? Do you select the best model based on its cross-validated performance, or do you use in-sample measures like AIC? If so, there is a way to improve your selection process further.</p>
<p>JORS recently published the paper of Nikos Kourentzes and I based on a simple but powerful idea: instead of using summary statistics (like the mean RMSE of cross-validated errors), you should consider the entire distribution and choose a specific quantile. This aligns with <a href="https://openforecast.org/2024/03/27/what-does-lower-error-measure-really-mean/">my previous post on error measures</a>, but here is the core intuition:</p>
<p>The distribution of error measures is almost always asymmetric. If you only look at the average, you end up with a &#8220;mean temperature in the hospital&#8221; statistic, which doesn&#8217;t reflect how models actually behave. Some models perform great on most series but fail miserably on a few.</p>
<p>What can we do in this case? We can look at quantiles of distribution.</p>
<p>For example, if we use 84th quantile, we compare the models based on their &#8220;bad&#8221; performance, situations where they fail and produce less accurate forecasts. If you choose the best performing model there, you will end up with something that does not fail as much. So your preferences for the model become risk-averse in this situation.</p>
<p>If you focus on the lower quantile (e.g. 16th), you are looking at models that do well on the well-behaved series and ignore how they do on the difficult ones. So, your model selection preferences can be described as risk-tolerant, because you are accept that the best performing model might fail on a difficult time series.</p>
<p>Furthermore, the median (50th quantile, the middle of sample), corresponds to the risk-neutral situation, because it ignores the tails of the distribution.</p>
<p>What about the mean? This is a risk-agnostic strategy, because it says nothing about the performance on the difficult or easy time series &#8211; it takes everything and nothing in it at the same time, hiding the true risk profile.</p>
<p>So what?</p>
<p>In the paper, we show that using a risk-averse strategy tends to improve overall forecasting accuracy in day-to-day situations. Conversely, a risk-tolerant strategy can be beneficial when disruptions are anticipated, as standard models are likely to fail anyway.</p>
<p>So, next time you select a model, think about the measure you are using. If it’s just the mean RMSE, keep in mind that you might be ignoring the inherent risks of that selection.</p>
<p>P.S. While the discussion above applies to the distribution of error measures, our paper specifically focused on point AIC (in-sample performance). But it is a distance measure as well, so the logic explained above holds.</p>
<p>P.P.S. Nikos wrote a <a href="https://www.linkedin.com/posts/nikos-kourentzes-3660515_forecasting-datascience-analytics-activity-7414687127269007360-pLAh">post about this paper here</a>.</p>
<p>P.P.P.S. And here is <a href="https://github.com/trnnick/working_papers/blob/fd1973624e97fc755a9c2401f05c78b056780e34/Kourentzes_2026_Incorporating%20risk%20preferences%20in%20forecast%20selectionk.pdf">the link to the paper</a>.</p>
<p>Message <a href="https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/">Risky business: how to select your model based on risk preferences</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
