BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
igsteo
Calcite | Level 5
data work.monthlystock;
set work.stock;
if date = Intnx('MONTH', date, 0, 'END');
run;

I have managed to use the codes attached to filter 'monthly' price data.

 

Thank you

1 ACCEPTED SOLUTION

Accepted Solutions
mkeintz
PROC Star

@igsteo wrote:
data price;
set pricedata;
if date=intnx('weekday',intnx('month',date,0,'e'),0);
run;

These are my current codes which works except that two months are still missing i.e. 30th july 2020 and 29th December 2020. 

 

How should i modify the codes such that it reflects these two specific data as well?

 

alternative method i was thinking is could i specify that 31st July 2020, 30th and 31st December 2020 is a holiday. Hence, it will be excluded in the codes above for working days of the week?

If so, what are the codes?

 

Thank you

 


You could do exactly what I showed you in the case of weekly prices, where Fridays are not always trading days.  Compare the date in the current record with the data in the upcoming record - getting the interval between them in months (using the INTCK function).  If a month-end boundary is crossed between them, then keep the current record.

 

My week-oriented code was:

data want;
  set stocks;
  by stockid;
  if eod2=0 then set stocks (firstobs=2 keep=date rename=(date=nxt_date)) end=eod2;
  else nxt_date='31dec2030'd;

  if intck('week.7',date,nxt_date)>0 or last.stockid;
run;

For end of month, just change "week.7" to "month", as in (I'll also change the data set names).  I've also dropped the "by stockid" since your data rows are apparently not grouped by stockid: 

data price;
  set pricedata;
  if eod2=0 then set pricedata (firstobs=2 keep=date rename=(date=nxt_date)) end=eod2;
  else nxt_date='31dec2030'd;

  if intck('month',date,nxt_date)>0;
run;

The second SET statement starts out at observation 2, so it is always one obs in advance of the current obs from the first SET, giving you a way to look ahead at the next date.  The reason it has an "if eod2=0" clause is because a SET without the IF would end the data step one iteration prematurely, since it starts out at obs 2.

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------

View solution in original post

11 REPLIES 11
PeterClemmensen
Tourmaline | Level 20

Show us your data please.

ballardw
Super User

@igsteo wrote:
data work.monthlystock;
set work.stock;
if date = Intnx('MONTH', date, 0, 'END');
run;

The historical data of the stock is 2007-11-07 to 2021-01-19.

I have managed to use the codes attached to filter 'monthly' price data.

 

However, how do i filter to get weekly price data?

 

Thank you


Please describe what specific period, as in days of the week and such that you are looking for.

mkeintz
PROC Star

If the last trading day of every week were on a Friday, then you could do something analogous to your code:

 

data work.monthlystock;
  set work.stock;
  if date = Intnx('WEEK.7', date, 0, 'END');
run;

But not all Fridays are trading days.  Instead you might want the last trading day of the week (where "week" is defined as starting on Saturday and ending on Friday, i.e.  "week.7" in sas date-interval terms.

 

So you could look for the last trading day such that the next trading is in the next "week.7" period, as in:

 

data want;
  set stocks;
  by stockid;
  if eod2=0 then set stocks (firstobs=2 keep=date rename=(date=nxt_date)) end=eod2;
  else nxt_date='31dec2030'd;

  if intck('week.7',date,nxt_date)>0 or last.stockid;
run;

This assume data are sorted by stockid/date.

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
igsteo
Calcite | Level 5

 

data mylib.mnprice;
set mylib.pricedata;
if date = Intnx('MONTH', date, 0, 'END');
run;

The following are my codes and the output. However, i realise months are missing as you can see january 2016, april 2016 is not included. 

 

My start date is 31DEC2015 to 29DEC2020. 

 

How do i include missing months where the date is 28th or 29th?

 

Thank you

Kurt_Bremser
Super User
data intermediate;
set have;
week = intnx('week',date,0,'e');
run;

proc sql;
create table want as
  select
    date,
    price
  from intermediate
  group by week
  having date = max(date)
;
quit;
    

This will always get you the last date that is present for a given week. A week would only miss if there was not even a single price point within that week.

 

The code is not tested in any way, as no usable data was provided.

igsteo
Calcite | Level 5
data price;
set pricedata;
if date=intnx('weekday',intnx('month',date,0,'e'),0);
run;

These are my current codes which works except that two months are still missing i.e. 30th july 2020 and 29th December 2020. 

 

How should i modify the codes such that it reflects these two specific data as well?

 

alternative method i was thinking is could i specify that 31st July 2020, 30th and 31st December 2020 is a holiday. Hence, it will be excluded in the codes above for working days of the week?

If so, what are the codes?

 

Thank you

 

mkeintz
PROC Star

@igsteo wrote:
data price;
set pricedata;
if date=intnx('weekday',intnx('month',date,0,'e'),0);
run;

These are my current codes which works except that two months are still missing i.e. 30th july 2020 and 29th December 2020. 

 

How should i modify the codes such that it reflects these two specific data as well?

 

alternative method i was thinking is could i specify that 31st July 2020, 30th and 31st December 2020 is a holiday. Hence, it will be excluded in the codes above for working days of the week?

If so, what are the codes?

 

Thank you

 


You could do exactly what I showed you in the case of weekly prices, where Fridays are not always trading days.  Compare the date in the current record with the data in the upcoming record - getting the interval between them in months (using the INTCK function).  If a month-end boundary is crossed between them, then keep the current record.

 

My week-oriented code was:

data want;
  set stocks;
  by stockid;
  if eod2=0 then set stocks (firstobs=2 keep=date rename=(date=nxt_date)) end=eod2;
  else nxt_date='31dec2030'd;

  if intck('week.7',date,nxt_date)>0 or last.stockid;
run;

For end of month, just change "week.7" to "month", as in (I'll also change the data set names).  I've also dropped the "by stockid" since your data rows are apparently not grouped by stockid: 

data price;
  set pricedata;
  if eod2=0 then set pricedata (firstobs=2 keep=date rename=(date=nxt_date)) end=eod2;
  else nxt_date='31dec2030'd;

  if intck('month',date,nxt_date)>0;
run;

The second SET statement starts out at observation 2, so it is always one obs in advance of the current obs from the first SET, giving you a way to look ahead at the next date.  The reason it has an "if eod2=0" clause is because a SET without the IF would end the data step one iteration prematurely, since it starts out at obs 2.

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
igsteo
Calcite | Level 5
proc sql;
create table reits_rp as
select a.*, b.date, b.VAR3, a.*/b.VAR3 as reit_rp
from return as a, bondyield as b
where a.date=b.date;
quit;

 

a= picture showing stock returns

b= picture showing bond yield

 

As show above my codes using proc sql i would like to form a new table where every stock returns (a) minus yield (b) and by date. However, the log reflects an error in 'a.*/b.VAR3'

How do i rectify this?

Thank you

Kurt_Bremser
Super User

You want to divide ALL variables in table RETURN (including the date value!) by VAR3 from table BONDYIELD, and store the result in a single column? How should that work?

Such formulas need single variables/columns, you cannot use the asterisk there.

igsteo
Calcite | Level 5
 

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 11 replies
  • 1471 views
  • 1 like
  • 5 in conversation