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

Hello,

 

I have a dataset looks like:

 

iddatereturnreport dateavg. return
10001/1/20001.11/5/20001.7
10001/2/20001.21/5/20001.7
10001/3/20001.31/5/20001.7
10001/4/20001.41/5/20001.7
10001/5/20001.51/5/20001.7
10001/6/20001.61/5/20001.7
10001/7/20001.71/5/20001.7
10001/8/20001.81/5/20001.7
10011/1/20001.91/3/20002.3
10011/2/200021/3/20002.3
10011/3/20002.11/3/20002.3
10011/4/20002.21/3/20002.3
10011/5/20002.31/3/20002.3
10011/6/20002.41/3/20002.3
10011/7/20002.51/3/20002.3
10021/1/20002.61/4/20003.05
10021/2/20002.71/4/20003.05
10021/3/20002.81/4/20003.05
10021/4/20002.91/4/20003.05
10021/5/200031/4/20003.05
10021/6/20003.11/4/20003.05

 

What I need is to select a number of returns for each id based on the report dates. The returns selected are those within a 3-day window since the report date. After the selection, I want to calculate the average of the selected returns and output results as avg. return. I also want the sql query has certain flexibility that allows me to quickly specify other n-day windows, such as a 20-day window with 10 days prior to the report date and 10 days after.

 

I wrote a preliminary code but it seems not work as I intended:

 

%let begdate = 0;
%let enddate = 5;
proc sql; create table want as 
select a.*, mean(b.return) as avgret
from have as a left join
     have as b 
on a.id=b.id and a.date=b.date
where b.date between intnx('WEEKDAY', rptdate, &begdate) and intnx('WEEKDAY', rptdate, &enddate)
order by a.permno,a.date;
quit;

I appreciate your help on how to achieve this. Thank you.

1 ACCEPTED SOLUTION

Accepted Solutions
PGStats
Opal | Level 21

No need for a join here:

 

data have;
input id date :mmddyy. return	rptDate :mmddyy. avgRet;
datalines;
1000	1/1/2000	1.1	1/5/2000	1.7
1000	1/2/2000	1.2	1/5/2000	1.7
1000	1/3/2000	1.3	1/5/2000	1.7
1000	1/4/2000	1.4	1/5/2000	1.7
1000	1/5/2000	1.5	1/5/2000	1.7
1000	1/6/2000	1.6	1/5/2000	1.7
1000	1/7/2000	1.7	1/5/2000	1.7
1000	1/8/2000	1.8	1/5/2000	1.7
1001	1/1/2000	1.9	1/3/2000	2.3
1001	1/2/2000	2	1/3/2000	2.3
1001	1/3/2000	2.1	1/3/2000	2.3
1001	1/4/2000	2.2	1/3/2000	2.3
1001	1/5/2000	2.3	1/3/2000	2.3
1001	1/6/2000	2.4	1/3/2000	2.3
1001	1/7/2000	2.5	1/3/2000	2.3
1002	1/1/2000	2.6	1/4/2000	3.05
1002	1/2/2000	2.7	1/4/2000	3.05
1002	1/3/2000	2.8	1/4/2000	3.05
1002	1/4/2000	2.9	1/4/2000	3.05
1002	1/5/2000	3	1/4/2000	3.05
1002	1/6/2000	3.1	1/4/2000	3.05
;

%let priorDays = 3;
%let afterDays = 0;

proc sql; 
create table want as 
select 
    id, 
    rptDate format=yymmdd10.,  
    mean(return) as avgRet
from have
where intck("weekday", date, rptDate) between -&priorDays. and &afterDays.
group by id, rptDate;
quit;
PG

View solution in original post

4 REPLIES 4
Tom
Super User Tom
Super User

You didn't specify which day of the interval you wanted INTNX() to generate. 

Options as BEGINNING, END, or SAME.

Default is BEGINNING.

 

PeterClemmensen
Tourmaline | Level 20

I assume you want the 'sameday' argument in the INTNX function like this?

 

data have;
input id $ date:mmddyy10. return reportdate:mmddyy10. avgreturn;
format date reportdate mmddyy10.;
datalines;
1000 1/1/2000 1.1 1/5/2000 1.7
1000 1/2/2000 1.2 1/5/2000 1.7
1000 1/3/2000 1.3 1/5/2000 1.7
1000 1/4/2000 1.4 1/5/2000 1.7
1000 1/5/2000 1.5 1/5/2000 1.7
1000 1/6/2000 1.6 1/5/2000 1.7
1000 1/7/2000 1.7 1/5/2000 1.7
1000 1/8/2000 1.8 1/5/2000 1.7
1001 1/1/2000 1.9 1/3/2000 2.3
1001 1/2/2000 2 1/3/2000 2.3
1001 1/3/2000 2.1 1/3/2000 2.3
1001 1/4/2000 2.2 1/3/2000 2.3
1001 1/5/2000 2.3 1/3/2000 2.3
1001 1/6/2000 2.4 1/3/2000 2.3
1001 1/7/2000 2.5 1/3/2000 2.3
1002 1/1/2000 2.6 1/4/2000 3.05
1002 1/2/2000 2.7 1/4/2000 3.05
1002 1/3/2000 2.8 1/4/2000 3.05
1002 1/4/2000 2.9 1/4/2000 3.05
1002 1/5/2000 3 1/4/2000 3.05
1002 1/6/2000 3.1 1/4/2000 3.05
;

%let begdate = 0;
%let enddate = 5;
proc sql; create table want as 
select a.*, mean(b.return) as avgret
from have as a left join
     have as b 
on a.id=b.id and a.date=b.date
where b.date between intnx('WEEKDAY', a.reportdate, &begdate., 's') and intnx('WEEKDAY', a.reportdate, &enddate., 's')
order by a.id,a.date;
quit;
PGStats
Opal | Level 21

No need for a join here:

 

data have;
input id date :mmddyy. return	rptDate :mmddyy. avgRet;
datalines;
1000	1/1/2000	1.1	1/5/2000	1.7
1000	1/2/2000	1.2	1/5/2000	1.7
1000	1/3/2000	1.3	1/5/2000	1.7
1000	1/4/2000	1.4	1/5/2000	1.7
1000	1/5/2000	1.5	1/5/2000	1.7
1000	1/6/2000	1.6	1/5/2000	1.7
1000	1/7/2000	1.7	1/5/2000	1.7
1000	1/8/2000	1.8	1/5/2000	1.7
1001	1/1/2000	1.9	1/3/2000	2.3
1001	1/2/2000	2	1/3/2000	2.3
1001	1/3/2000	2.1	1/3/2000	2.3
1001	1/4/2000	2.2	1/3/2000	2.3
1001	1/5/2000	2.3	1/3/2000	2.3
1001	1/6/2000	2.4	1/3/2000	2.3
1001	1/7/2000	2.5	1/3/2000	2.3
1002	1/1/2000	2.6	1/4/2000	3.05
1002	1/2/2000	2.7	1/4/2000	3.05
1002	1/3/2000	2.8	1/4/2000	3.05
1002	1/4/2000	2.9	1/4/2000	3.05
1002	1/5/2000	3	1/4/2000	3.05
1002	1/6/2000	3.1	1/4/2000	3.05
;

%let priorDays = 3;
%let afterDays = 0;

proc sql; 
create table want as 
select 
    id, 
    rptDate format=yymmdd10.,  
    mean(return) as avgRet
from have
where intck("weekday", date, rptDate) between -&priorDays. and &afterDays.
group by id, rptDate;
quit;
PG
Zerg
Calcite | Level 5

Thank you!

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 4 replies
  • 1083 views
  • 2 likes
  • 4 in conversation