I have noted two slightly different definitions of idiosyncratic stock return volatility in:

- Campbell, J. Y. and Taksler, G. B. (2003), Equity Volatility and Corporate Bond Yields.
*The Journal of Finance*, 58: 2321–2350. doi:10.1046/j.1540-6261.2003.00607.x - Rajgopal, S. and Venkatachalam, M. (2011), Financial reporting quality and idiosyncratic return volatility.
*Journal of Accounting and Economics*, 51: 1–20. doi.org/10.1016/j.jacceco.2010.06.001.

The code in this post is used to calculate Campbell and Taksler’s (2003) idiosyncratic stock return volatility, but it can be easily modified for other definitions.

Specifically, this code requires an input dataset that includes two variables: `permno`

and `enddt`

, where `enddt`

is the date of interest. This code will calculate the standard deviation of daily abnormal returns over the 180 calendar days before (and including) `enddt`

. Abnormal returns will be calculated using four methods: (1) market-adjusted; (2) standard market model; (3) Fama-French three factors; and (4) Fama-French three factors as well as momentum. This code requires at least 21 return observations (one-month trading days) over that 180-day period for a `permno`

to calculate its stock return volatility.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
libname local "D:\Dropbox"; * Remote signon and upload input database including permno and date; %let wrds=wrds-cloud.wharton.upenn.edu 4016; options comamid=TCP remote=WRDS; signon username=_prompt_; rsubmit; proc upload data=local.input out=input; run; * Get raw returns and FF risk factors; proc sql; create table rets as select a.*, b.date, b.ret, c.smb, c.hml, c.umd, d.vwretd as mktret, (b.ret-d.vwretd) as exret from input a left join crsp.dsf b on a.permno=b.permno and a.enddt-180<b.date<=a.enddt left join ff.factors_daily c on b.date=c.date left join crsp.dsi d on b.date=d.date order by a.permno, a.enddt, b.date; quit; * Estimate factor exposures; proc printto log=junk; run; proc reg data=rets edf outest=params noprint; by permno enddt; eq0: model exret=; eq1: model ret=mktret; eq2: model ret=mktret smb hml; eq3: model ret=mktret smb hml umd; run; proc printto; run; * Compute abnormal returns for all models for each trading day; data abrets; merge rets (in=a) params (where=(_model_='eq0') keep=permno enddt _model_ _rmse_ _p_ _edf_ rename=(_rmse_=std0 _p_=p0 _edf_=edf0)) params (where=(_model_='eq1') keep=permno enddt _model_ _rmse_ intercept mktret rename=(_rmse_=std1 intercept=alpha1 mktret=beta1)) params (where=(_model_='eq2') keep=permno enddt _model_ _rmse_ intercept mktret smb hml rename=(_rmse_=std2 intercept=alpha2 mktret=beta2 smb=sminb2 hml=hminl2)) params (where=(_model_='eq3') keep=permno enddt _model_ _rmse_ intercept mktret smb hml umd rename=(_rmse_=std3 intercept=alpha3 mktret=beta3 smb=sminb3 hml=hminl3 umd=umind3)); by permno enddt; var0=std0**2; var1=std1**2;var2=std2**2;var3=std3**2; abret0=exret; expret1=alpha1+beta1*mktret; abret1=ret-expret1; expret2=alpha2+beta2*mktret+sminb2*smb+hminl2*hml; abret2=ret-expret2; expret3=alpha3+beta3*mktret+sminb3*smb+hminl3*hml+umind3*umd; abret3=ret-expret3; nobs=p0+edf0; /*number of observations used in estimation*/ drop p0 edf0 std0 std1 std2 std3 _model_ exret; if a and nobs>=21; run; proc sort data=abrets; by permno enddt date; run; proc means data=abrets noprint; by permno enddt; output out=retvol std(abret0)=vol0 std(abret1)=vol1 std(abret2)=vol2 std(abret3)=vol3; run; * Download output dataset and remote signoff; proc download data=retvol out=local.retvol; run; endrsubmit; signoff; |

Thank you very much for the idiosyncratic stock return volatility SAS code. It will help me so much in my research.

I’ve quick questions:

1- What is (a) dataset in the code?

2- Does the code calculate the daily or monthly idiosyncratic?

Hi Kai,

Thanks for sharing the code.

I just find that in Campbell and Taksler (2003) “Equity Volatility and Corporate Bond Yields”, they didn’t calculate idiocyncratic volatility as you did. (Although your code is good).

The following is a quote from their paper (Page 2330) “To summarize firm-level risk and return, we compute the mean and standard deviation of daily excess returns, relative to the CRSP value-weighted index, for each firm’s equity over the 180 days preceding (not including) the bond transac tion date. Thus, we avoid estimating betas for individual firms on the market in dex, effectively imposing a beta of one (and an alpha of zero) in the market model. Campbell, Lo, and MacKinlay (1997, p. 156) call this a “market-adjusted-return” model. We also include the mean and standard deviation of daily market returns, where the market is defined as the CRSP value-weighted index over the same 180 days. We expect the standard deviation of daily excess returns to have a positive effect on yield spreads

“

Actually, you did what they did by calculating (ret-mktret). I didn’t see that. Apologize!

Hi,

Thanks for sharing the IVOL code! Much appreciated. By the way, can we use the std1/std2/std3 directly as IVOL? Is it the same as vol1/vol2/vol3 ?

Thanks!

Hi Kai,

Thanks for posting the code. Do you by any chance also have this code in Stata as well.

Best, Shekhar