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.
%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".
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
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, 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
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
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.
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
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.
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;
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 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.