BookmarkSubscribeRSS Feed
Lapis Lazuli | Level 10

I want to know how to run this program. in other word the data file name and the variable that I must include in the data

/* */
/* Program: Option-Based Factors */
/* Author : Luis Palacios, WRDS */
/* Date : 03/01/2010 */
/* Revised : 03/29/2010 */
/* Steps : */
/* - Get Daily option prices for all S&P500 options */
/* - S&P500 (SPX) secid in optionmetrics is 108105 */
/* - Filters applied on 1st trading day of month */
/* - Keep options expiring in the following month */
/* - Keep only options with available prices */
/* - Keep options with standard settlements */
/* */
/* Notes on SPX Options: */
/* - Expiration: Saturday Following the 3rd Friday of Expiration Month */
/* - Exercise Style: European exercisable on last bus day bef. exp. */
/* */
/* Example: %optionfactor(begyear=1996,endyear=2009, */
/* flag=C,atm_otm=OTM,outfile=myfinalOTM); */
/* ******************************************************************* */

%macro optionfactor

data a1;
set %do i=&begyear %to &endyear; OPTIONM.OPPRCD&i
(keep = date secid exdate strike_price best_bid best_offer optionid
exdate ss_flag cp_flag where = (secid=&sp500_id)) %end; ;
month = month(date);
year = year(date) ;
/* Keep Options with Standard Settlment, i.e. 0 Special. Settl. Flag */
if ss_flag='0' and cp_flag="&flag" and best_bid>0 and best_offer>0;
/* Mid-Price */
price = (best_bid + best_offer)/2;
/* Strike Price Adjustment */
/* Standard SPX option expire Saturday (weekday=7)following the third Friday of the expiration month */
if weekday(exdate)=7; * it eliminates non standard-date options;
drop ss_flag cp_flag best_bid best_offer strike_price;

/* Sort Dataset to Keep First Observation per Month */
proc sort data=a1 out=a1; by optionid year month date; run;

/* Use Data from the First Trading Day of the Month */
/* Keep only Options that Expire in the Following Month */
data a2; set a1;
by optionid year month date;
if first.month;
if intck('month',date,exdate)=1;

/* Get Price of the underlying index (S&P 500) */
data b1;
set %do i=&begyear %to &endyear %by 1;
optionm.secprd&i (where = (secid=&sp500_id)) %end; ;
month = month(date);
year = year(date);
/* CLOSE is closing price at the end of the day */
keep date year month close secid;

/* Sort Price Data */
proc sort data=b1 out=b1; by secid year month date; run;

/* Keep data on first day of the month */
data b2; set b1;
by secid year month date;
if first.month;

/* Add Risk-Free Rate for Present Value Calculation */
proc sql;
create table b3 as
select a.rf, b.*
from ff.factors_monthly as a, b2 as b
where a.year=b.year and a.month=b.month;

/* Merge Option data with price data to identify moneyness */

/* Discount Rate for Strike Price of options expiring at 'exdate' */
%let discount = (( 1 + b.rf) ** ( -( )) ;

/* Select option whose Strike Price PV is closest to current price */
proc sql;
create table _list as
select, a.secid, a.price, a.exdate, a.strike , b.close,
a.optionid, a.strike*&discount - b.close as diff
from a2 as a, b3 as b
group by
having abs(diff)=min(abs(diff));

%if &atm_otm=ATM %then %goto finalstep;

/* Next Step is for OTM options Exclusively */

%else %if &atm_otm=OTM %then %do;
%if &flag=C %then %let sign = < ;
%else %if &flag=P %then %let sign = > ;

proc sql undo_policy=none;
create table _list2 as
select b.*, ((a.close + abs(a.diff)) - b.strike) as diff2
from _list(keep=date strike close diff) as a, a2 as b
where and
( a.close + abs(a.diff) ) &sign b.strike /* Out the money OTM PUT sign is positive, OTM CALL sign is negative */
a.strike &sign b.strike
group by
having abs(diff2)=min(abs(diff2)) ;

/* Final Step bookmark */

%if &atm_otm=ATM %then %let inputfile= _list ;
%else %if &atm_otm=OTM %then %let inputfile= _list2 ;

/* For selected options grab prices at the beg. of the next month */

proc sql;
create table &outfile as
select intnx('month',,0,'end') as DATE format yymmddn8.,
(b.price/a.price)-1 as Factor_Ret "Option-Based Factor" format percentn8.2,
"&flag" as flag, "&atm_otm" as money
from &inputfile as a, a1 as b
where a.optionid=b.optionid and intck('month',,
group by
order by ;


You need a LIBNAME statement that defines a folder identified as OPTIONM:


libname OPTIONM 'path to folder';


WIthin that folder, you need SAS data sets covering the range of years that you would like to analyze:







The range of years needed can change, depending on the values supplied when calling the macro.  The default ranges from 1996 to 2012, but you can override that by specifying begyear= and endyear=.

Lapis Lazuli | Level 10

so I need a number of folder equal to the number of year that I have form 1996 to 2012. then 17 .sas7bdat???



You just need one folder.  The name of the folder doesn't matter, but you have to include it in the LIBNAME statement.


All the SAS data sets need to reside in that folder.



Secure your spot at the must-attend AI and analytics event of 2024: SAS Innovate 2024! Get ready for a jam-packed agenda featuring workshops, super demos, breakout sessions, roundtables, inspiring keynotes and incredible networking events.


Register by March 1 to snag the Early Bird rate of just $695! Don't miss out on this exclusive offer. 


Register now!

What is Bayesian Analysis?

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 2 in conversation