Hey,
I have to replicate the Momentum Strategy where the formation window for my portfolios is "t-12" -"t-2". That means that every month I have to find the stocks with the highest(lowest) cumulative returns ( during the past 12 months) and allocate them into different buckets. The formation period is from t-12 to t-2 since I need to skip one month. The following code is meant to help with this, but I dont see intck statement skipping 1 month. I addition to this, when I constrcut the weights and the returns of the portfolios I get the opposite results of a momentum strategy.
Any comments would be much appreciated.
let %J= 12
let % K= 1
/* Creating momentum measures based on past 12 (J) Month Compounded Returns*/
proc sql;
create table umd
as select distinct a.permno, a.date,a.Mkcap, exp(sum(log(1+b.ret))) - 1 as cum_return
from msex2 (keep=permno date MKcap) as a, msex2 as b
where a.permno=b.permno and 0<= intck("month", b.date, a.date) <&J
group by a.permno, a.date
having count(b.ret)=&J;
quit; * Keep stocks with available return info in the formation period;
proc sort data=umd; by date; run;
proc rank data=umd out=umd1 group=10;
by date;
var cum_return;
ranks momr;
run;
data umd2;
set umd1(drop=cum_return);
momr=momr+1;
* MOMR is the portfolio rank variable taking values between 1 and 10:
1 - the lowest momentum group
10 - the highest momentum group;
label momr = "Momentum Portfolio";
run;
/* Assign Ranks to the Next 1 (K) Months After Portfolio Formation*/
******************************************************************************
***;
* Portfolio return are average monthly returns rebalanced monthly;
proc sql;
create table msfx2
as select distinct a.momr, a.date as form_date, a.permno,a.Mkcap, b.date, b.ret
from umd2 as a, msex2 as b
where a.permno=b.permno
and 0<intck("month",a.date,b.date)<=&K;
quit;
If the formation window is t-12 through t-2 (an eleven month window), shouldn't your criterion be
where a.permno=b.permno and &K< intck("month", b.date, a.date) <=&J
...
having count(b.ret) = %eval(&J-&K)
I take K is the size of the gap (in months) between the end of the formation window and the current date. I.e. with J=12 and K=1, then to form a window in December, use the months of then prior December through current October.
You can use the macro function %eval(&J=&K) to generalize the program.
If the formation window is t-12 through t-2 (an eleven month window), shouldn't your criterion be
where a.permno=b.permno and &K< intck("month", b.date, a.date) <=&J
...
having count(b.ret) = %eval(&J-&K)
I take K is the size of the gap (in months) between the end of the formation window and the current date. I.e. with J=12 and K=1, then to form a window in December, use the months of then prior December through current October.
You can use the macro function %eval(&J=&K) to generalize the program.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.