Hi there,
I am trying to calculate month-end idiosyncratic volatility for every stocks with 250 daily returns (at least 125 data points).
I came across the macro %idvol in WRDS however this program doesn't allow for 1 month step. The only thing I can do is to run it for every day.
Given that, it seems very troublesome and time-consuming to calculate IVOL for all stocks for 40 years of analysis
IS there any way to get around this problem? Can we modify the program to make it jump every month?
Thank you very much for any help!
Dennis
The code is presented below:
/* ********************************************************************************* */
/* ******************** W R D S R E S E A R C H M A C R O S ******************** */
/* ********************************************************************************* */
/* WRDS Macro: IDVOL */
/* Summary : Calculates idiosyncratic volatility using time-series monthly/daily */
/* regressions for various risk models */
/* Date : July 07, 2009 */
/* Author : Denys Glushkov, WRDS */
/* Variables : - INSET and OUTSET are input and output datasets */
/* - DATEVAR: name of the date variable in INSET dataset */
/* - RETVAR : name of the raw return variable in INSET dataset */
/* - FREQ : frequency of returns in incoming INSET dataset, */
/* m (monthly) or d(daily) */
/* - WINDOW : the length of the rolling estimation window in */
/* months/trading days over which the idiosyncratic volatility*/
/* is estimated */
/* - STEP : number of months/trading days by which the estimation */
/* window is rolled forward */
/* - MIN : minimum number of non-missing returns in the esitmation */
/* window required for generating valid estimates of IDVOL */
/* - MODEL : risk model used in estimation of idiosyncratic volatility */
/* m (market), ff (Fama-French 3 factor), ffm (FF+Momentum) */
/* ********************************************************************************* */
%MACRO
IDVOL (INSET=, OUTSET=, DATEVAR=, RETVAR=, FREQ=,
WINDOW
=,STEP=,
MIN
=, MODEL=);
%local
oldoptions errors;
%let
oldoptions=
%sysfunc
(getoption(mprint))
%sysfunc
(getoption(notes))
%sysfunc
(getoption(source));
%let
errors=
%sysfunc
(getoption(errors));
options
nonotes nomprint nosource errors=0;
%let
model=
%lowcase
(
&model
);
%let
freq=
%lowcase
(
&freq
);
/*Depending on the incoming return frequency, create ancillary macro variables*/
%if
&freq
=m
%then
%do
;
%let
file
=monthly;
%let
inc
=
month
;
%let
dateff=dateff;
%end
;
%else
%if
&freq
=d
%then
%do
;
%let
file
=daily;
%let
inc
=
day
;
%let
dateff=
date
;
%end
;
/*Depending on the type of the risk model, create the variable list to be extracted*/
%if
&model
=m
%then
%let
vars=mktrf;
%else
%if
&model
=ff
%then
%let
vars=mktrf smb hml;
%else
%if
&model
=ffm
%then
%let
vars=mktrf smb hml umd;
%put
### CREATING TRADING CALENDAR;
proc
printto
log
=junk;
%Trade_Date_Windows
(freq=
&freq
, size=
&window
, minsize=
&min
, outdsn=_caldates);
proc
printto;
run
;
%put
### DONE!;
%put
### MERGING
IN
THE RISK FACTORS;
proc
sql noprint; create table _vol
as select a.*, b.*, (
&retvar
-rf) as exret
from
&inset
a
left
join ff.factors_
&file
(
keep
=
&dateff
rf
&vars
) b
on
a.
&datevar
=b.
&dateff
order
by
a.permno, a.
&datevar
;
select distinct
min
(
&datevar
) format date9.,
max
(
&datevar
) format date9. into :mindate,:maxdate
from _vol;
quit
;
%put
### DONE!;
/*Save the beginning and ending position of the earliest */
/*and the latest dates in the trading calendar */
data
_caldates;
set
_caldates;
n
+1;
if
intnx
(
'month'
,beg_date,0,
'e'
)=
intnx
(
'month'
,
"&mindate"
d,0,
'e'
)
then
call symput (
'start'
,
n
);
if
intnx
(
'month'
,end_date,0,
'e'
)=
intnx
(
'month'
,
"&maxdate"
d,0,
'e'
)
then
call symput (
'finish'
,
n
);
run
;
/*Main part. Estimate Idiosyncratic Volatility using */
/*rolling time-series regressions. Boundaries for */
/*regressions are based on start and end dates in the */
/*trading calendar */
%put
### ESTIMATING IDIOSYNCRATIC VOLATILITY;
proc
printto
log
=junk;
run
;
%do
j=
&start
%to
&finish
%by
&step
;
data
_null_
;
set
_caldates (sortedby=
n
where=(
n
=
&j
));
call symput (
'beg'
,beg_date);call symput (
'end'
,end_date);
run
;
data
_sample/
view
=_sample;
do
k=1
by
1
until
(last.permno);
set
_vol;
by
permno;
where
&beg
<=
date
<
&end
;
if
missing(ret)
then
continue;
mcount=
sum
(mcount,1);
end
;
keep
permno mcount;
run
;
data
_vvol/
view
=_vvol;
merge
_vol (sortedby=
date
where=(
&beg
<=
date
<
&end
)) _sample;
by
permno;
if
mcount>=
&min
;
drop
mcount;
run
;
proc
reg
data
=_vvol edf noprint outest=_stats;
by
permno;
model exret=
&vars
;
quit
;
data
_stats;
set
_stats;
format start_date end_date date9.;
start_date=
&beg
;end_date=
&end
;
nused=_p_+_edf_;
label
_rmse_ =
" "
; rename _rmse_=Idrisk_std;
keep
permno start_date end_date _rmse_ nused;
run
;
/*Pool all estimates of idiosyncratic risk together*/
proc
append base=_idvol
data
=_stats force;
run
;
%end
;
proc
printto;
run
;
/*Merge the incoming dataset with idiosyncratic risk estimates*/
proc
sql; create table
&outset
as select *
from
&inset
a
left
join _idvol b
on
a.permno=b.permno and a.
date
=b.end_date;
/* house cleaning*/
drop
table _stats, _vol, _caldates;
drop
view
_vvol, _sample;
quit
;
options
&oldoptions
errors=
&errors
;
%put
### DONE!;
%put
###
OUTPUT
IN
THE DATASET
&outset
;
%MEND
;
Subset the data perhaps?
You might want to post the code of this macro or at least where you found it. A google search only returns this message thread when I search for it.
Hi, I just copied and pasted the code here for easy reference!
Hi:
The code doesn't help without the data. WRDS seems to be the Wharton Research Data Services at the U of Penn. Are you using the data from the server? Did the program have an author? It might work better for you to contact the program author, who must be already familiar with the data you are using.
cynthia
Hi Cynthia,
The data is from WRDS (UPenn) as well. For example, I can choose the inset to be crsp daily data so I set the frequency to be daily.
You are right. Maybe I should ask the program author.
It looks like the macro has a parameter freq=m that implies it does monthly processing of some kind, i.e. sets inc= monthly.
The call to macro Trade_date_windows also is another place to look for processing issues.
Any idea if there are other nested macros in Trade_date_windows? Every one might be an issue for the processing you want.
Just ask your question to your orignal problem before finding that macro.
It could be outdated.
This macro contains calls to intnx SAS(R) 9.3 Functions and CALL Routines: Reference that is build for shifting in time
there are a lot of financial functions implemented. They are documented by SAS to their normal standards. I assume it is OASIS/java stadnard based. SAS(R) 9.4 Functions and CALL Routines: Reference, Second Edition
You are probablyl into Basel-III Market-Risk, being described as part of SAS Riskmanagement http://www.sas.com/offices/europe/belux/pdf/events/20101209_10yLux/SAS-RiskManagement-Luxembourg-10y...
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.
Find more tutorials on the SAS Users YouTube channel.