BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Sinistrum
Quartz | Level 8

Dear community,

 

I would be glad, if you were to provide help concerning my following issue.

 

Core of my question: Is there (an equivalent of) a sum operator in the "proc model" environment?

 

Explicit setting/example:

I am running the following regression, where I am trying to estimate the an exponential decay function, where y is assumed to be an exponentially weighted sum of lagged x-es.

baseline model.PNG

 

 

 

%ODSOff;
proc model
		data	=	in;


        	endo 	=	y;
         	exog
				x_l1-x_l18;

         	parms
				a
				b
				l;



		mflow	 =
							a	+	

							b * (
							exp(-l*(0))*x_l1+
							exp(-l*(1))*x_l2+
							exp(-l*(2))*x_l3+
							exp(-l*(3))*x_l4+
							exp(-l*(4))*x_l5+
							exp(-l*(5))*x_l6+
							exp(-l*(6))*x_l7+
							exp(-l*(7))*x_l8+
							exp(-l*(8))*x_l9+
							exp(-l*(9))*x_l10+
							exp(-l*(10))*x_l11+
							exp(-l*(11))*x_l12+
							exp(-l*(12))*x_l13+
							exp(-l*(13))*x_l14+
							exp(-l*(14))*x_l15+
							exp(-l*(15))*x_l16+
							exp(-l*(16))*x_l17+
							exp(-l*(17))*x_l18);

		 	fit mflow
				/ gmm;

		 	ods output
				ParameterEstimates			=	ParameterEstimates_sine_exp_x
				ResidSummary				=	ResidSummary_sine_exp_x;

run; quit;
%ODSOn;

 

This is the skeleton of the model.

 

 

 

Next, I add covariates.

Among this, there are a many indicator variables.

E.g., I want to use "time dummies".

For the sake of it, please let us assume I do not want to de-mean, I like to have distinct coefficient estimates.

The sample has is that there are 192 time points, i.e. 192 indicator variables, i.e. 191 regressors for my model for I want to keep a, the model's intercept.

 

As of now, I used a very-quick-and-dirty-way: Generate a list of "t2*month_indicator2 + ... + t192*month_indicator192" conveniently in Excel and copy-paste it.

The code becomes even more messy than it already is.

Thus, I would like to have something like a sum-operator in the vein "sum from i=2 to 192: ti*month_indicatori".

timedummy model.PNG

 

If it is of any importance, I am trying to replicate the method by Barber/Huang/Odean (2016) ("Which Factors Matter to Investors? Evidence from Mutual Fnd Flows") and it is ought to be equation (5).

 

Yours sincerely

Sinistrum

1 ACCEPTED SOLUTION

Accepted Solutions
Puwang
Obsidian | Level 7

You need to put it in a macro. Do the following outside your proc model statement:

%macro sum_script();
%do i = 2 %to 191;
	t&i.*month_indicator&i. +
%end;
t192*month_indicator192;
%mend;

Then call %sum_script; in proc model where you insert the summation function.

View solution in original post

7 REPLIES 7
Puwang
Obsidian | Level 7

Sinistrum, you can use macro statement to generate the summation list:

%do i = 2 %to 191;
	t&i.*month_indicator&i. + 
%end;
t192*month_indicator192

The above statement will give you:

t2*month_indicator2 + t3*month_indicator3 +... + t192*month_indicator192

 

Hope this helps.

 

Thanks,

Pu

 

Sinistrum
Quartz | Level 8

Thank you Puwang, but I receive the error 'The %DO statement is not valid in open code.'.
This is how I implemented the idea of yours:

 

%ODSOff;
proc model
		data	=	in;


        	endo 	=	y;
         	exog
				x_l1-x_l18
				month_indicator2-month_indicator192;

         	parms
				a
				b
				l
				t2-t192;



		mflow	 =
							a	+	

							b * (
							exp(-l*(0))*x_l1+
							exp(-l*(1))*x_l2+
							exp(-l*(2))*x_l3+
							exp(-l*(3))*x_l4+
							exp(-l*(4))*x_l5+
							exp(-l*(5))*x_l6+
							exp(-l*(6))*x_l7+
							exp(-l*(7))*x_l8+
							exp(-l*(8))*x_l9+
							exp(-l*(9))*x_l10+
							exp(-l*(10))*x_l11+
							exp(-l*(11))*x_l12+
							exp(-l*(12))*x_l13+
							exp(-l*(13))*x_l14+
							exp(-l*(14))*x_l15+
							exp(-l*(15))*x_l16+
							exp(-l*(16))*x_l17+
							exp(-l*(17))*x_l18)
	
							+	

							/* Your suggestion as I understood */
							%do i = 2 %to 191;
								t&i.*month_indicator&i. + 
							%end;
							t192*month_indicator192;

		 	fit mflow
				/ gmm;

		 	ods output
				ParameterEstimates			=	ParameterEstimates_sine_exp_x
				ResidSummary				=	ResidSummary_sine_exp_x;

run; quit;
%ODSOn;

 

 

Yours sincereley

Sinistrum

Puwang
Obsidian | Level 7

You need to put it in a macro. Do the following outside your proc model statement:

%macro sum_script();
%do i = 2 %to 191;
	t&i.*month_indicator&i. +
%end;
t192*month_indicator192;
%mend;

Then call %sum_script; in proc model where you insert the summation function.

Sinistrum
Quartz | Level 8

First, please excuse me for being clumsy,

second, thank you very much indeed.

 

I can make use of this at so many instances in my codes - I appreciate it a lot.

 

Yours sincerely

Sinistrum

Puwang
Obsidian | Level 7

Glad that I can help.

 

To make it more convenient, you can just wrap your entire proc model statement (or more code) within a macro, so that you do not need to create extra macros for each %do loop you created.

For example:

 

%macro call_model();
proc model
		data	=	in;


        	endo 	=	y;
         	exog
				x_l1-x_l18
				month_indicator2-month_indicator192;

         	parms
				a
				b
				l
				t2-t192;



		mflow	 =
				a	+	
				b * (
                                        %do i = 1 %to 18;
                                          %let j = %eval(&i-1);
                                          exp(-l*(&j))*x_l&i. +
				        %end;

					%do i = 2 %to 191;
						t&i.*month_indicator&i. + 
					%end;
					t192*month_indicator192;

		 	fit mflow
				/ gmm;

		 	ods output
				ParameterEstimates	=	ParameterEstimates_sine_exp_x
				ResidSummary		=	ResidSummary_sine_exp_x;

run; quit;
%mend;

And then call %call_model;

There are also some useful options when you use sas macro, especially useful for debugging:

options mprint;
options mlogic;
options symbolgen;

The MPRINT option writes to the SAS log each SAS statement generated by a macro.

The MLOGIC option traces the flow of execution of your macro, including the resolution of parameters.

The SYMBOLGEN option tells you what each macro variable resolves to by writing messages to the SAS log.

kessler
SAS Employee

PROC MODEL provides many facilities for implementing models like this one.  Besides using macros you can use arrays, or the SUM function:

proc model ...;
   endo y;
   exog x1-x10 ind1-ind10;
   parms a l t1-t10;

   array t[10] t1-t10;
   array x[10] x1-x10;
   array ind[10] ind1-ind10;
   array tmp[10];

   do i = 1 to 10;
      tmp[i] = exp(-l*(i-1))*x[i]
               + t[i]*ind[i];              
   end;

   y = a + sum (of tmp1-tmp10);

   fit y;
quit;
Sinistrum
Quartz | Level 8

This comes in very handy, thank you very much.

Keeps it all tidied up and in one place in the 'proc model' statement.

I may use multiple 'tmp' as you dubbed them, with different lengths and then fit them together in the actual model equation.

 

 

And thank you for elaborating on your answer and given even more hints on how I could improve further, Pu.

 

 

Astonishing, how quickly this request has been solved one again.

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

Multiple Linear Regression in SAS

Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 7 replies
  • 1972 views
  • 10 likes
  • 3 in conversation