We’re smarter together. Learn from this collection of community knowledge and add your expertise.

How to build custom models in PROC TSMODEL

by SAS Employee YueLi on ‎02-14-2018 02:59 PM - edited a month ago by Community Manager (1,461 Views)


For automatic forecasting of large numbers of time series, the ATSM packages provides access to the most robust models available today based on diagnosing the characters of each time series. However, for experienced forecasters, sometimes you might have the desire to create your own model based on industry related insights. This paper describes how to build custom model using Time Series Model (TSM) package in PROC TSMODEL.


The reader of this paper is assumed to have already known about PROC TSMODEL (if not, please read PROC TSMODEL 101 first).


Time Series Model (TSM) package Overview

The time series model (TSM) package surfaces a set of time series modeling objects that provide a flexible way to model and forecast univariate time series. It contains:

  • The TSM class encapsulates the computational services for all univariate time series models.
  • Model specification classes that allow you to construct time series model definitions (specifications) which define the characteristics of time series model instances.
  • Collector classes that can operate on the time series model (TSM) objects to collect and persist various results from the time series model execution (e.g. fit statistics, forecasts, parameter estimates, model specifications, etc).
  • Repeater classes that serve as conduits to replay model specifications and model parameter estimates to TSM objects.


The object classes in the TSM package are described briefly here:




Time series model class used to forecast univariate time series models


ARIMA model specification class used to define custom ARIMA models


Exponential Smoothing Model (ESM) model specification class used to define custom ESM models


Intermittent Demand Model (IDM) model specification class used to define custom IDM models.


Unobserved Component Model (UCM) model specification class used to define custom UCM models


External Model (EXM) model specification class used to define external forecast computations


Collector class used to store time series model parameter estimates from a TSM instance.


Collector class used to store time series model XML.


Collector for TSM model forecasts


Repeater class used to replay time series model parameter estimates from a CAS table.


Repeater class used to replay time series model XML specifications from a CAS table.


For a detailed description, synopsis and methods of each object in the TSM package, please click here.


For experienced SAS users, the TSMODEL procedure and TSM package are designed to provide functionality and capabilities that are similar to what is available with the following SAS 9.4 procedures:

  • ESM
  • UCM
  • HPFXXXSPEC (where XXX stands for ARIMA, ESM, IDM, UCM and EXM) + HPFENGINE

Build a Custom Model

Now, we will talk about how to build custom models using TSM model, so that it can be reused in the subsequent TSMODEL calls. The steps are simple:

  • Declare TSM objects
  • Specify the model(s) by configuring a model specification object.
  • Run the model and collect the corresponding results

 Let’s walk through the steps by several examples.


Example 1: Build an Exponential Smoothing Model (ESM) model

In this example, we take the airline passenger data from sashelp library, fit a Winters model with multiplicative seasonality, and forecast 12 periods out.

cas mycas;

libname mylib cas sessref = mycas;


data mylib.aircas;

   set sashelp.air;  


proc tsmodel data=mylib.aircas





*use TSM package;

register tsm;


id date interval=month;

var air;

outarray predict;

outscalar nfor mase;



     *declare TSM objects;

     declare object spec(esmspec);

     declare object esm(tsm);


     *specify ESM model parameters;

     rc = spec.Open();

     rc = spec.SetTransform('log','median');

     rc = spec.SetOption('method', 'winters');

     rc = spec.SetOption('criterion', 'mase');

     rc = spec.Close();


     *set time series, run ESM model;

     rc = esm.Initialize(spec);

     rc = esm.SetY(air);

     rc = esm.Run();


     *collect the statistics from the model;

     nfor = esm.nfor();

     mase = esm.criterion('fit');


     *collect the forecasts into object called predict;

     rc = esm.GetForecast('predict',predict);





*print the output tables;

proc print data=mylib.scalars; run;

proc print data=mylib.predict; run;


The process flow in the program statement block of PROC TSMODEL is as follows:

First, we declared the required TSM objects, an instance for ESMSPEC class object and an instance for TSM class object.

Next, we specify the parameters for this ESM model. It includes instructing the code to take logarithm transformation of the prediction variable, use median as prediction semantics for the inverse transform, use multiplicative Winters model, and set MASE as the model estimation criterion.


Then we set up the dependent variable, air, and run the ESM model.


Finally, we collect some statistics from the model into the scalar output table, and the forecast results into the array output table.

Let us take a look at the output tables. The scalar output table “mylib.scalars” displays the size of the predict series “nfor” and the mean absolute standard error “mase”.


The array output table “mylib.predict” includes the basic columns of outarray table, and a column we named as “predict” in the code for forecast results. Below is a screen capture of the first couple of rows for this table.


Example 2: Build an ARIMA model

Based on the same data, now let’s build a different model, a moving average model Yt=0.25yt-1+0.25yt-2+0.25yt-3+0.25yt-4.


proc tsmodel data=mylib.aircas



register tsm;

id date interval=month;

var air;

outarray predict;


        *moving average forecasts;

        declare object mavgSpec(ARIMASPEC);

        declare object mavgTsm(TSM);


        *specify moving average model parameters;

        rc = mavgSpec.open();

        *setup spec for moving average of window 4;

        beta = 1/4;

        array AROrder[4]/nosymbols;

        array ARCoeff[4]/nosymbols;

        AROrder[1] = 1; AROrder[2] = 2; AROrder[3] = 3; AROrder[4] = 4;

        ARCoeff[1] = beta; ARCoeff[2] = beta;

        ARCoeff[3] = beta; ARCoeff[4] = beta;


        rc = mavgSpec.addARPoly(AROrder, 4, 0, ARCoeff);

        *no estimate, no intercept;

        rc = mavgSpec.setOption('noint', 1, 'noest', 1, 'nostable', 1);

        rc = mavgSpec.close();


        *setup the TSM object;

        rc = mavgTsm.initialize(mavgSpec);

        rc = mavgTsm.setY(air);

        rc = mavgTsm.setOption('lead', 12);

        rc = mavgTsm.run();


        *collect the forecast;

        rc = mavgTsm.getForecast('predict', predict);





To build moving average model, we use the ARIMASPEC object. The code above specifies the 4 AR terms and their corresponding orders, coefficients for the 4 terms, add these orders and coefficients into the ARIMASPEC instance mavgSpec, and set the options to make sure no intercept is included and no estimation is needed. After running the specified model, we collect the forecast results.


Example 3: Build an ARIMAX model

Below is an example illustrating how to specify an ARIMAX model, which considers both the dependent variable and independent variables in the model. This example also shows how to collect the results through TSM object method.


cas mycas;

libname mylib cas sessref = mycas;


*prepare the input data;

data mylib.pricedata;

    set sashelp.pricedata;


*extend 12 periods out;

proc tsmodel data = mylib.pricedata

             out  = mylib.pricedata_aug

             lead = 12;

    by regionname productline productname;

    id date interval=month;

    var sale /acc = sum setmiss=miss;

    var price/acc = avg setmiss=PREV;


*fill out the independent variable values for the future 12 periods;

proc tsmodel data = mylib.pricedata_aug

             out  = mylib.pricedata_ext;

    by regionname productline productname;

    id date interval=month;

    var sale /acc = sum setmiss=miss;

    var price/acc = avg setmiss=PREV;



*build the ARIMAX model;

proc tsmodel data   = mylib.pricedata_ext

             outobj = (

                       outFor  = mylib.outFor

                       outEst  = mylib.outEst


    by regionname productline productname;

    id date interval=month;

    var sale /acc = sum;

    var price/acc = avg;


    *use TSM package;

    require tsm;


        *declare TSM objects;

        declare object arima(ARIMASPEC);

        declare object tsm(TSM);

        declare object outest(TSMPEST);

        declare object outfor(TSMFOR);


        array diff[1]/nosymbols (1);

        array ar[3]/nosymbols (1 2 3);

        array ma[1]/nosymbols (1);


        *specify arima model parameters arima (3,1,0)(0,0,1)s with x(1);

        rc = arima.open();


        *usage: rc = ARIMASpec.SetDiff(DiffArray[,NDiff]);

        rc = arima.setDiff(diff);


        *usage: rc = ARIMASpec.AddARPoly(OrderArray[,NOrder,Seasonal,CoeffArray]);

        rc = arima.addARPoly(ar,3,0);


        *usage: rc = ARIMASpec.AddMAPoly(OrderArray[,NOrder,Seasonal,CoeffArray]);

        rc = arima.addMAPoly(ma,1,1);


        *usage: rc = ARIMASpec.AddTF(XName[,Delay,DiffArray,NDiff]);

        rc = arima.addTF('price', 0, diff);


        rc = arima.setOption('method', 'ml');

        rc = arima.close();


        *set options: y and x variables, lead, model;

        rc = tsm.initialize(arima);

        rc = tsm.setY(sale);

        rc = tsm.addX(price);

        rc = tsm.setOption('lead',12);

        rc = tsm.run();


        *collect the forecasts into object called outfor;

        rc = outfor.collect(tsm);

        *collect the estimates into object called outest;

        rc = outest.collect(tsm);




In a summary, this code requires the TSM package, utilizes ARIMASPEC to define the model, uses TSM object to fit the model, and then generates two output tables using the collect method of the TSM object instance.


The process flow is as follows:

First, we start by specifying the seasonal ARIMA model (3,1,0)(0,0,1)s with differencing X using ARIMASPEC object instance. We do this by specifying the differencing on dependent variable, autoregressive (AR) polynomial factor, and moving average (MA) polynomial factor using the corresponding methods. Then we add a differencing function to the model for the specified independent variable “price”. We also set the option to make the sure model will be estimated based on maximal likelihood function.


Next, we initialize the TSM object instance based on the ARIMA model we specified. We define the time series for analysis by adding the dependent variable (sale) and independent variable (price) into the TSM object. After specifying the forecast lead to be 12, we instruct the TSM object instance to estimate and forecast the time series sale based on the ARIMA model.


Finally, we collect the relevant forecast results and model estimation results for review and downstream processes. The output of the collected objects are saved in CAS tables. They can be reviewed for forecasting validation and improvement. The OUTEST table, can also be used as inputs to the repeater objects in user-defined programs to customize the time series analysis workflows.


Let us take a look at the output tables.  Below is a description of the available output tables, with a screen capture of the first couple of rows for each table.


The forecast table (mylib.outFor) includes the forecast results with the STD and UPPER & LOWER values for each time series.

The estimate table (mylib.outEst) includes the estimates of the model parameters for each time series.



This document has briefly introduced TSM package in PROC TSMODEL, demonstrated how to create custom models and generate forecast using TSM package. For more information, please see the documentation for the TSM packages, and PROC TSMODEL in the SAS Viya forecasting documentation.

Your turn
Sign In!

Want to write an article? Sign in with your profile.

Looking for the Ask the Expert series? Find it in its new home: communities.sas.com/askexpert.