Message Boards Message Boards

Seasonality indexation with the Wolfram Language

Posted 7 years ago

Decomposition Approach

ABSTRACT

Seasonality in economic data plays important part in econometric forecasting and predictions for future business decisions. In this respect, understanding and estimation of seasonality patterns in inflation data is essential component of pricing decisions for any payoffs linked to inflation. We present decomposition method for inflation seasonality detection – a simple, but robust technique for seasonality detection. Thanks for to flexibility of powerful Wolfram Programming Language, the implementation is quick and efficient with accomplishment in just few steps

enter image description here

Seasonality in economic data

Economic time series are known to exhibit fluctuation and distortions. These tend to occur in periodic intervals. Fluctuations that last several years and occur in regular intervals are know as business cycles, whereas variations driven by seasonal characteristics and occurring typically within a year are called seasonality. The understanding of seasonality is important because many business and economic data are seasonal. Seasonality, especially when strong, can hide important features such as trends and cyclicity, and therefore proper understanding of seasonality is important pre-requisite for understanding time series. If seasonality is material, its detection and anticipation can male different between correct and incorrect business decision.

Seasonality is typical feature of GDP measurement, labor statistics, retail sales, construction activity and strongly characterizes inflation processes. This is the primary focus of this analysis.

Seasonality can be measured in several ways. We examine first the so-called decomposition methods, which are one of the oldest techniques in econometric modeling and forecasting.

Time series components

Time series can be decomposed into a set of fundamental components with its own unique characteristic. In the basic format, the time series at any point of time Subscript[Y, t] can be expressed as multi-factors model:

enter image description here

where f denotes the model's function, T is the trend, C is the cyclical component, S is the seasonality influence and e is the error term.

Trend and cyclical factors represent a 'growth' pattern in time series, and usually are modelled together. MutiThis is because a separation of trend from cyclicality is not simple. Although seasonality can be formulated on any time interval, quarterly and monthly variations are most common. The error term is a residual component of time series that is not explained by trend, cycle or seasonality. It's random and thus unpredictable.

Decomposition models

There are tow major decomposition models:

enter image description here

DecoThe choice of the model depends on the nature of time series. If the plot of the data revelers the independence of seasonality and cycle from the general level, then using additive model is a right decision. However, when factors are dependent on each other (eg. seasonality varies due to the trend / cycle), choosing multiplicative model is a right strategy to follow.

Multiplicative model is more common in the econometric studies and is also a preferred choice for extraction of inflation seasonality.

Multiplicative seasonal model

Decomposition method for multiplicative model uses the ratio of moving averages and centered smoothing to determine seasonal factors. We will demonstrate the approach on the UK RPI data.

We take the UK RPI history from Jan 1987 up to Oct 2016 and create the time series object

ukrpi = {100, 100.4, 100.6, 101.8, 101.9, 101.9, 101.8, 102.1, 102.4, 
   102.9, 103.4, 103.3, 103.3, 103.7, 104.1, 105.8, 106.2, 106.6, 
   106.7, 107.9, 108.4, 109.5, 110, 110.3, 111, 111.8, 112.3, 114.3, 
   115, 115.4, 115.5, 115.8, 116.6, 117.5, 118.5, 118.8, 119.5, 120.2,
    121.4, 125.1, 126.2, 126.7, 126.8, 128.1, 129.3, 130.3, 130, 
   129.9, 130.2, 130.9, 131.4, 133.1, 133.5, 134.1, 133.8, 134.1, 
   134.6, 135.1, 135.6, 135.7, 135.6, 136.3, 136.7, 138.8, 139.3, 
   139.3, 138.8, 138.9, 139.4, 139.9, 139.7, 139.2, 137.9, 138.8, 
   139.3, 140.6, 141.1, 141, 140.7, 141.3, 141.9, 141.8, 141.6, 141.9,
    141.3, 142.1, 142.5, 144.2, 144.7, 144.7, 144, 144.7, 145, 145.2, 
   145.3, 146, 146, 146.9, 147.5, 149, 149.6, 149.8, 149.1, 149.9, 
   150.6, 149.8, 149.8, 150.7, 150.2, 150.9, 151.5, 152.6, 152.9, 153,
    152.4, 153.1, 153.8, 153.8, 153.9, 154.4, 154.4, 155, 155.4, 
   156.3, 156.9, 157.5, 157.5, 158.5, 159.3, 159.5, 159.6, 160, 159.5,
    160.3, 160.8, 162.6, 163.5, 163.4, 163, 163.7, 164.4, 164.5, 
   164.4, 164.4, 163.4, 163.7, 164.1, 165.2, 165.6, 165.6, 165.1, 
   165.5, 166.2, 166.5, 166.7, 167.3, 166.6, 167.5, 168.4, 170.1, 
   170.7, 171.1, 170.5, 170.5, 171.7, 171.6, 172.1, 172.2, 171.1, 172,
    172.2, 173.1, 174.2, 174.4, 173.3, 174, 174.6, 174.3, 173.6, 
   173.4, 173.3, 173.8, 174.5, 175.7, 176.2, 176.2, 175.9, 176.4, 
   177.6, 177.9, 178.2, 178.5, 178.4, 179.3, 179.9, 181.2, 181.5, 
   181.3, 181.3, 181.6, 182.5, 182.6, 182.7, 183.5, 183.1, 183.8, 
   184.6, 185.7, 186.5, 186.8, 186.8, 187.4, 188.1, 188.6, 189, 189.9,
    188.9, 189.6, 190.5, 191.6, 192, 192.2, 192.2, 192.6, 193.1, 
   193.3, 193.6, 194.1, 193.4, 194.2, 195, 196.5, 197.7, 198.5, 198.5,
    199.2, 200.1, 200.4, 201.1, 202.7, 201.6, 203.1, 204.4, 205.4, 
   206.2, 207.3, 206.1, 207.3, 208, 208.9, 209.7, 210.9, 209.8, 211.4,
    212.1, 214, 215.1, 216.8, 216.5, 217.2, 218.4, 217.7, 216, 212.9, 
   210.1, 211.4, 211.3, 211.5, 212.8, 213.4, 213.4, 214.4, 215.3, 216,
    216.6, 218, 217.9, 219.2, 220.7, 222.8, 223.6, 224.1, 223.6, 
   224.5, 225.3, 225.8, 226.8, 228.4, 229, 231.3, 232.5, 234.4, 235.2,
    235.2, 234.7, 236.1, 237.9, 238, 238.5, 239.4, 238, 239.9, 240.8, 
   242.5, 242.4, 241.8, 242.1, 243, 244.2, 245.6, 245.6, 246.8, 245.8,
    247.6, 248.7, 249.5, 250, 249.7, 249.7, 251, 251.9, 251.9, 252.1, 
   253.4, 252.6, 254.2, 254.8, 255.7, 255.9, 256.3, 256, 257, 257.6, 
   257.7, 257.1, 257.5, 255.4, 256.7, 257.1, 258, 258.5, 258.9, 258.6,
    259.8, 259.6, 259.5, 259.8, 260.6, 258.8, 260, 261.1, 261.4, 
   262.1, 263.1, 263.4, 264.4, 264.9, 264.8};
rpits = TimeSeries[ukrpi, {{1987, 1, 1}, {2016, 10, 1}, "Month"}];
DateListPlot[rpits, PlotLabel -> Style["UK RPI 1987 - 2016", 15], 
 PlotStyle -> {Blue, Thick}, Filling -> Axis]

enter image description here

To proceed with seasonality calculation, we apply the moving average (MA) technique twice:

enter image description here

mova1 = MovingAverage[rpits, 12];
mova2 = MovingAverage[mova1, 2];
DateListPlot[{rpits, mova2}, 
 PlotLabel -> Style["RPI series and their averages", 15], 
 PlotLegends -> {"RPI", "C-MA"}, PlotStyle -> {Thick, {Blue, Red}}]

enter image description here

The use of centered moving averages is practical, but not exhaustive and we can apply further smoothing techniques to adjust the data. Exponential smoothing is one of them.

mova3 = ExponentialMovingAverage[mova2, 0.25];
DateListPlot[{mova2, mova3}, 
 PlotLabel -> Style["Centered MA and their exponential smoothing", 15], 
 PlotLegends -> {"C-MA", "Exp-S"}]

enter image description here

In the next steps we calculate the ratio of moving averages where the original series are divided by their MA

newrpi=TimeSeriesWindow[rpits,{mova3["FirstTime"],{2016,10,1}}];
rat1=newrpi/mova3;
DateListPlot[rat1,PlotLabel->Style["Ratio of MA",15],Filling->Axis]

enter image description here

The ratio above is essentially the S*e quantity obtained from time series. To eliminate the randomness from the data, we simply average the value over the 12-monthly intervals.

rawseas=Table[Mean[Take[rat1["Values"],{i,Length[rat1["Values"]],12}]],{i,1,12}]

{1.0179878778325224,1.020865454219894,1.0220704288011477,1.0283140969748503, 1.0292781053076343,1.0282757052368627,1.0237944649874124,1.0252818857730472, 1.0269539388642832,1.025905611864363,1.0244253764240674,1.024069255746688}

The 'raw' seasonal indices are the first-level results we aim to achieve. We perform further adjustment to the indices to ensure they sum up to 12

rpiseas=(12/Total[rawseas])*rawseas
lab={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
DateListPlot[rpiseas,{2015,1},PlotLabel->Style["UK PRI Seasonal Indices",15],
    PlotStyle->{Red,Thick},Mesh->Full,PlotMarkers->Automatic, InterpolationOrder->1,ImageSize->400]
BarChart[{1-rpiseas},ChartElementFunction->"GlassRectangle",ChartStyle->"Rainbow",
    ChartLabels->lab,PlotLabel->Style["UK RPI - monthly seasonal variations",15],ImageSize->400]

{0.993383, 0.996191, 0.997367, 1.00346, 1.0044, 1.00342, 0.999049, 1.0005, 1.00213, 1.00111, 0.999665, 0.999318}

enter image description here

enter image description here

What does the result tell us? The UK RPI seasonality tends to be low in the first quarter of the year, then higher in the second quarter and mixed in the second half of the year.

De-seasonalising inflation data

Having obtained the seasonal indices, we can now de-seasonalise the RPI data. From the decomposition formula this is simply

enter image description here

deseasRpi = newrpi["Values"]/PadRight[rpiseas,Length[newrpi["Values"]],rpiseas];
DateListPlot[deseasRpi,{1988,1},PlotLabel->Style["De-seasonalised UK RPI",15],
PlotStyle->{Magenta,Thick},Filling->Axis,FillingStyle->LightGray]

enter image description here

Obtaining the trend for inflation data

Once the de-seasonalised series are available, we can proceed further and estimate the trend and cyclicality in the inflation data.

Trends can be usually estimated with some regression techniques, with Linear being the simplest. Mathematica, however, offers more elegant solutions. Two alternatives include:

enter image description here

Interpolation

We can choose from few alternatives in terms of order. Linear or Quadratic model will fit the RPI data well.

trendInt = ListInterpolation[deseasRpi, InterpolationOrder -> 2, 
  Method -> "Spline"]; ListLinePlot[trendInt, 
 PlotLabel -> Style["Cyclical trend in the UK RPII", 15], 
 PlotStyle -> {Red, Thickness[0.009]}]

enter image description here

ListPlot[{Take[deseasRpi, -66], Table[trendInt[i], {i, 280, 346}]}, 
 PlotStyle -> {Blue, {Orange, Thickness[0.009]}}, Joined -> {False, True}, 
 PlotLabel -> Style["Cyclical trend - last 5Y focus", 15]]

enter image description here

Data science route

We can also use the most recent advances in Mathematica and use the new function FindFormula that tries to find symbolic function to the underlying data.

trendFrm = FindFormula[deseasRpi, t]

enter image description here

Automatic fit finds the piecewise formula that can be easily applied to visualize and generate functional data.

ListPlot[{Take[deseasRpi, -47], Table[trendFrm, {t, 300, 345}]}, 
 Joined -> {False, True}, PlotLabel -> Style["De-seasonalised RPI and its trend - most recent data", 15], 
 PlotStyle -> {Blue, {Red, Thick}}, PlotRange -> {240, 265}, 
 PlotLegends -> {"Deseas RPI", "Trend"}, ImageSize -> 400]

enter image description here

Additive seasonal model

Methods and steps devised in the multiplicative seasonal model can be re-applied in the additive model that instead of division and multiplication operates on subtraction and addition. We will perform the following steps:

enter image description here

addDiff=newrpi-mova3;
rawseasadd=Table[Mean[Take[addDiff["Values"],{i,Length[addDiff["Values"]],12}]],{i,1,12}];
rpiseasadd=rawseasadd-Mean[rawseasadd]

{-1.22689, -0.661592, -0.42587, 0.535942, 0.713983, 0.569999, -0.172041, 0.122327, 0.432471, 0.234763, -0.0640571, -0.0590322}

We can verify the correctness of the calculation by ensuring:

a) sum of additive seasonalities is equal to zero

b) average of all additive seasonalities is zero as well

{Total[rpiseasadd], Mean[rpiseasadd]} // Round

{0, 0}

DateListPlot[rpiseasadd,{1015,1},PlotStyle->{Magenta,Thick},Mesh->Full,PlotMarkers->Automatic, 
    InterpolationOrder->1, PlotLabel->Style["Additive UK RPI seasonalities",15],ImageSize->400]
BarChart[{rpiseasadd},ChartElementFunction->"GlassRectangle",ChartStyle->"TemperatureMap",
    ChartLabels->lab,PlotLabel->Style["UK RPI variations", 15],ImageSize->400]

enter image description here

enter image description here

It is not surprising to see the additive seasonalities being similar to the multiplicative ones. This shows both models identify similar seasonality characteristics that govern UK RPI series over the longer interval.

Regression approach in decomposition methods

Regression technique is a flexible technique for finding relationship between data, and, as such, can also be used to model seasonality in inflation series. When seasonality is modelled through regression, all series components have to be defined as as regression variables that influence the response. In this respect, we define (i) trend and (ii) 11 monthly seasonal variables that we egress against the RPI series.

For the regression model, we choose shorter series pattern with 16 years of PRI data

rpireg = TimeSeriesWindow[rpits, {{2000, 1, 1}, {2015, 12, 1}}];
vals = rpireg["Values"];

We create table of data in the matrix format enter image description here

tbl1 = Table[If[i == j, 1, 0], {i, 0, 11}, {j, 1, 11}];
tbl2 = Table[tbl1, {16}];
tbl3 = Flatten[tbl2, 1];
tbl4 = MapThread[Prepend, {tbl3, Range[16*12]}];
tbl5 = MapThread[Append, {tbl4, vals}];
tbl6 = MapThread[Append, {tbl4, Log[vals]}];
vars = {T, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12};

We now apply the multi-variate regression for the data

Regression model for additive seasonality

lmod2add = LinearModelFit[tbl5, vars, vars]

lmod2add // Normal

159.04 + 1.16312 S10 + 0.802768 S11 + 0.879919 S12 + 0.720902 S2 +

0.973054 S3 + 1.70646 S4 + 1.85236 S5 + 1.66701 S6 + 0.837911 S7 +

1.10881 S8 + 1.44846 S9 + 0.529098 T

We can now visualize the seasonality data

lmod2add["ParameterTableEntries"];
Take[%,All,1]//Flatten;
aregseas=Drop[%,1];
aregseas-Mean[aregseas];
ListLinePlot[%,PlotStyle->{Green,Thickness[0.006]},Mesh->Full,
    PlotLabel->Style["Additive seasonalities through regression",15],
    PlotMarkers->Automatic, InterpolationOrder->1,ImageSize->400]

enter image description here

We can look at goodness-of-fit statistics to check the quality of the model

Grid[Transpose[{#, lmod2add[#]} &[{"AdjustedRSquared", "AIC", "BIC", "RSquared"}]], Alignment -> Left]

enter image description here

The additive model fits the data quite well which is confirmed by high level of R-Squared statistics.

Regression model for multiplicative seasonality

Multiplicative model uses the same set of market data, with only change being the response vector that is transformed though a Log function

lmod2mul = LinearModelFit[tbl6, vars, vars]

lmod2mul // Normal

5.09571 + 0.00568329 S10 + 0.00399881 S11 + 0.00423331 S12 + 0.00336445 S2 + 0.00463021 S3 + 0.00826615 S4 + 0.00908784 S5 + 0.0082519 S6 + 0.00423283 S7 + 0.00537755 S8 + 0.00707623 S9 + 0.00250739 T

lmod2mul["ParameterTableEntries"];
Take[%, All, 1] // Flatten;
mregseas = Exp[Drop[%, 1]];
mregseas = (12/Total[mregseas])*mregseas;
ListLinePlot[mregseas, PlotStyle -> {Purple, Thickness[0.006]}, 
 Mesh -> Full, PlotMarkers -> Automatic, InterpolationOrder -> 1, ImageSize -> 400, 
 PlotLabel -> Style["Multiplicative seasonality - regression approach", 15]]

enter image description here

We check the goodness-of-fit for the model:

Grid[Transpose[{#, lmod2mul[#]} &[{"AdjustedRSquared", "AIC", "BIC", "RSquared"}]], Alignment -> Left]

enter image description here

We observe even better fit for the multiplicative regression model with high R^2. This confirms that inflation seasonality is better modeled with multiplicative model than the additive one.

Conclusion

Decomposition method for time series is easy-to-apply technique that is well suited for inflation analysis with clear-cut seasonality output. Factorisation of inflation data into components allows quick identification of series drivers and detection of seasonality patterns which in turn affects forecasting. Although the decomposition is simple relative to more advanced seasonality models, it still provides desirable results that we well understory amongst market practitioners.

Decomposition, as this demonstration shows, is easily implemented in Mathematica where only few steps are required to generate seasonality indices from historical series.

Attachments:
POSTED BY: Igor Hlivka
3 Replies
Posted 7 years ago

HI! Interesting approach. Why won't you rely on standard TRAMO/SEATS or Census-X11-X12-X13 approaches?

POSTED BY: Alex Isakov

enter image description here - you have earned "Featured Contributor" badge, congratulations !

This is a great post and it has been selected for the curated Staff Picks group. Your profile is now distinguished by a "Featured Contributor" badge and displayed on the "Featured Contributor" board.

POSTED BY: Moderation Team

Hello

The idea was to present classical decomposition method in Wolfram Language. This is still widely used technique in econometrics. More advances methods based on ARIMA models share principles with this 'oldest' technique. I will be addressing other inflations-related topics shortly, and will try implementing more advanced models as well.

Thank you for your interest in this topic! Best IH

POSTED BY: Igor Hlivka
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract