Forecasting

Holidays Are No Vacation for the Load Forecaster

July 31, 2019

Summer has arrived. While your friends are frolicking at the beach, you are struggling in a darkened cubicle to ensure that the load forecast performs well on July 4.

Indeed, holidays create a unique challenge for load forecasters. There are two broad categories of holidays:

  • Stationary holidays occur on the same weekday each year. For example, Martin Luther King, Jr. Day is celebrated in the U.S. on the third Monday in January. Memorial Day is celebrated on the last Monday in May.
  • Non-stationary holidays occur on different weekdays. In the U.S., Independence Day is July 4, regardless of the weekday. Similarly, in Canada, Canada Day is always on July 1.

Typically, short-term load models use five or fewer years of historical data. This creates no intrinsic problems regarding the stationary holidays. It can create issues when it comes to non-stationary holidays, however, because the model has not experienced those holidays on all seven days of the week.
First, we will look at the stationary holidays. For MLK Day, you can specify the variable as follows:

Let’s unpack this:

  • Month = 1 returns a 1 during January and 0 otherwise
  • Weekday = 2 returns a 1 on Mondays and 0 otherwise

The third Monday will fall between (and including) the 15th and the 21st.

  • Day>=15 returns a 1 on all days after and including the 15th of each month
  • Day<=21 returns a 1 on all days before and including the 21st of each month

The product of each of these expressions is a 1 on the third Monday in January. We can use similar logic to define a Memorial Day variable.

Now, let’s look at the non-stationary holidays. We can define Independence Day as follows:

This variable will return a 1 on July 4 every year. From a modeling perspective, the problem arises because July 4 is sometimes on Tuesday and sometimes on Sunday. The effect of the holiday on a Tuesday will likely be different than the effect on a Sunday. To complicate the issue further, we may need to address the surrounding days as well. For instance, when July 4 is on a Saturday, the holiday is likely observed on Friday, July 3.

Let’s first look at how to specify the variable accounting for different weekdays. In the following example, Saturdays are weighted with a 0.4, Sundays are weighted with a 0.25 and all other days are weighted with a 1.0. In other words, Saturdays will get 40% of the impact of the weekdays, while Sundays will get 25% of the impact of the weekdays.

You can do some analysis of residuals to determine the weights that make sense for your load.

You can expand this idea further by specifying weights for July 3 and July 5 as well.

By specifying the weights in transforms, you can build complicated logic to address the issue. Further, a single variable that accounts for July 3, July 4 and July 5 can be a powerful way to address the problem of the holiday spillover effect along with the shifting weekday.

Before you get too excited about this, you should consider the following. By the time you get the non-stationary holiday effect right, the holiday has already happened. And, when the holiday happens, you won’t get it right because it hasn’t happened on that same day in seven years. In other words, you’ll get it right, but it will be just in time to be too late.

Have you seen the new Itron website? Be sure to visit the new forecasting page at www.itron.com/forecasting.

Si è verificato un errore nell'elaborarazione del modello.
The following has evaluated to null or missing:
==> authorContent.contentFields  [in template "44616#44647#114455" at line 9, column 17]

----
Tip: It's the step after the last dot that caused this error, not those before it.
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: contentFields = authorContent.content...  [in template "44616#44647#114455" at line 9, column 1]
----
1<#assign 
2	webContentData = jsonFactoryUtil.createJSONObject(author.getData()) 
3	classPK = webContentData.classPK 
4/> 
5 
6<#assign 
7authorContent = restClient.get("/headless-delivery/v1.0/structured-contents/" + classPK + "?fields=contentFields%2CfriendlyUrlPath%2CtaxonomyCategoryBriefs") 
8contentFields = authorContent.contentFields 
9categories=authorContent.taxonomyCategoryBriefs 
10authorContentData = jsonFactoryUtil.createJSONObject(authorContent) 
11friendlyURL = authorContentData.friendlyUrlPath 
12authorCategoryId = "0" 
13/> 
14 
15<#list contentFields as contentField > 
16   <#assign  
17	 contentFieldData = jsonFactoryUtil.createJSONObject(contentField)  
18	 name = contentField.name 
19	 /> 
20	 <#if name == 'authorImage'> 
21	    <#if (contentField.contentFieldValue.image)??> 
22	        <#assign authorImageURL = contentField.contentFieldValue.image.contentUrl />	 
23			</#if> 
24	 </#if> 
25	 <#if name == 'authorName'> 
26	    <#assign authorName = contentField.contentFieldValue.data /> 
27			<#list categories as category > 
28         <#if authorName == category.taxonomyCategoryName> 
29				     <#assign authorCategoryId = category.taxonomyCategoryId /> 
30				 </#if> 
31      </#list> 
32	 </#if> 
33	 <#if name == 'authorDescription'> 
34	    <#assign authorDescription = contentField.contentFieldValue.data /> 
35			 
36	 </#if> 
37	  
38	 <#if name == 'authorJobTitle'> 
39	    <#assign authorJobTitle = contentField.contentFieldValue.data /> 
40			 
41	 </#if> 
42 
43</#list> 
44 
45<div class="blog-author-info"> 
46	<#if authorImageURL??> 
47		<img class="blog-author-img" id="author-image" src="${authorImageURL}" alt="" /> 
48	</#if> 
49	<#if authorName??> 
50		<#if authorName != ""> 
51			<p class="blog-author-name">By <a id="author-detail-page" href="/w/${friendlyURL}?filter_category_552298=${authorCategoryId}"><span id="author-full-name">${authorName}</span></a></p> 
52			<hr /> 
53		</#if> 
54	</#if> 
55	<#if authorJobTitle??> 
56		<#if authorJobTitle != ""> 
57			<p class="blog-author-title" id="author-job-title" >${authorJobTitle}</p> 
58			<hr /> 
59		</#if> 
60	</#if> 
61	<#if authorDescription??> 
62		<#if authorDescription != "" && authorDescription != "null" > 
63			<p class="blog-author-desc" id="author-job-desc">${authorDescription}</p> 
64			<hr /> 
65		</#if> 
66	</#if> 
67</div>