Advertisement
Guest User

Untitled

a guest
Jul 26th, 2020
609
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
SAS 30.03 KB | None | 0 0
  1. /* Calculate ratios */
  2. /* ********************************************************************************* */
  3. /* ************** W R D S   R E S E A R C H   A P P L I C A T I O N S ************** */
  4. /* ********************************************************************************* */
  5. /* Summary   : The three-step macro code calculates financial ratios at both firm-   */
  6. /*             level and industry-level. Macro "FinRatio" calculates financial ratio */
  7. /*             at firm-level, macro "FinRatio_Firm" outputs the ratios, and macro    */
  8. /*             "FinRatio_Ind" aggregates financial ratios at user-selected industry  */
  9. /*             level.                                                                */
  10. /*                                                                                   */
  11. /* Date      : Feb 2016                                                              */
  12. /* Author    : Denys Glushkov, WRDS                                                  */
  13. /* Input     :                                                                       */
  14. /*   Universal Inputs                                                                */
  15. /*             - UNI_BEGDT  : Begin Date of the Sample (e.g. 01JAN1990)              */
  16. /*             - UNI_ENDDT  : End Date of the Sample (e.g. 31DEC2015)                */
  17. /*             - UNI_SP500  : Sample Selection S&P500 if=1, CRSP Common Stock if=0   */
  18. /*   Macro FinRatio Input                                                            */
  19. /*             - RATIOS_OUT : Output Data                                            */
  20. /*   Macro FinRatio_Firm Input                                                       */
  21. /*             - FIRMRATIOS : Output Data at Firm-Level                              */
  22. /*   Macro FinRatio_Ind Input                                                        */
  23. /*             - INDCODE    : GICS=GICS 10 Sectors, FF=Fama French Industries        */
  24. /*             - NIND       : Num of Industries (FF only) - 10, 12, 17, 30, 48, 49   */
  25. /*             - AVR        : Choice of Averaging - Median or Mean                   */
  26. /*             - INDRATIOS  : Output Data at Industry-Level                          */
  27. /*                                                                                   */
  28. /*                                                                                   */
  29. /* To run the program, a user should have access to CRSP daily and monthly stock,    */
  30. /* Compustat Annual and Quarterly sets, IBES and CRSP/Compustat Merged database      */
  31. /* ********************************************************************************* */
  32.  
  33. /* Set Universal Input Variables */
  34. %let uni_begdt = 01JAN2006;
  35. %let uni_enddt = 01JAN2020;
  36. %let uni_sp500 = 0;
  37.  
  38.  
  39. %MACRO FINRATIO (begdate=, enddate=, sp500=, ratios_out=);
  40.  
  41. /*Impose filter to obtain unique gvkey-datadate records*/
  42. %let compcond=indfmt='INDL' and datafmt='STD' and popsrc='D' and consol='C';
  43. %if &sp500=1 %then %let sp500_where=and sp500=1; %else %let sp500_where=and 1;
  44.  
  45. /*List of Ratios to be calculated*/
  46. %let vars=
  47.  pe_op_basic pe_op_dil pe_exi pe_inc ps pcf evm bm capei dpr npm opmbd opmad gpm ptpm cfm roa roe roce aftret_eq aftret_invcapx aftret_equity pretret_noa pretret_earnat
  48.  equity_invcap  debt_invcap totdebt_invcap int_debt int_totdebt cash_lt invt_act rect_act debt_at short_debt curr_debt lt_debt fcf_ocf adv_sale
  49.  profit_lct debt_ebitda ocf_lct lt_ppent dltt_be debt_assets debt_capital de_ratio intcov cash_ratio quick_ratio curr_ratio capital_ratio cash_debt
  50.  inv_turn  at_turn rect_turn pay_turn sale_invcap sale_equity sale_nwc RD_SALE Accrual GProf be cash_conversion efftax intcov_ratio staff_sale;
  51. %let allvars=&vars divyield ptb bm PEG_trailing PEG_1yrforward PEG_ltgforward;
  52. /*Compustat variables to extract*/
  53. %let avars=
  54.   SEQ ceq TXDITC  TXDB ITCB PSTKRV PSTKL PSTK prcc_f csho epsfx epsfi oprepsx opeps ajex ebit spi nopi
  55.   sale ibadj dvc dvp ib oibdp dp oiadp gp revt cogs pi ibc dpc at ni ibcom icapt mib ebitda xsga
  56.   xido xint mii ppent act lct dltt dlc che invt lt rect xopr oancf txp txt ap xrd xad xlr capx;
  57. /*Define which accounting variables are Year-To-Date, usually from income/cash flow statements*/
  58. %let vars_ytd=sale dp capx cogs xido xint xopr ni pi oibdp oiadp opeps oepsx epsfi epsfx ibadj ibcom mii ibc dpc xrd txt spi nopi;
  59.  
  60. proc sql noprint;
  61.  select distinct lowcase(name) into :qvars separated by ' '
  62.  from dictionary.columns
  63.  where libname='COMP' and memname='FUNDQ' and memtype='DATA'
  64.  and findw(lowcase("&avars."),substr(lowcase(name),1,length(name)-1))>0;
  65. quit;
  66.  
  67. data __compq0;
  68.  set comp.fundq
  69.   (keep=gvkey datadate fyr fyearq fqtr PRCCQ epsf12 dvy epsfi12
  70.         oepsxq oepsxy oepf12 oeps12 ibadj12 tic &qvars. teqq epsfxq);
  71.    if atq  <=0 then atq  =.;
  72.    if saleq<=0 then saleq=.;
  73. run;
  74.  
  75. proc sql;
  76. create table __compq1 as
  77. select * from __compq0;
  78. quit;
  79.  
  80. /*Quarterize the YTD flow accounting variables*/
  81. %QUARTERIZE(INSET=__compq1, OUTSET=__compq1, IDVAR=gvkey fyr, FYEAR=fyearq, FQTR=fqtr);
  82.  
  83. proc sort data=__compq1 nodupkey; by gvkey fyr fyearq fqtr; run;
  84. %macro ttm(var); (&var + lag1(&var) + lag2(&var) + lag3(&var)) %mend;
  85. %macro mean_year(var); mean(&var, lag1(&var), lag2(&var),lag3(&var)) %mend;
  86.  
  87. /*Prepare quarterly data: if quarterly Compustat variable is missing, replace with quarterized version*/
  88. data __compq2; set __compq1;
  89.  by gvkey fyr fyearq fqtr;
  90.   if SEQq>0 then BEq = sum(SEQq, TXDITCq, -PSTKq); if BEq<=0 then BEq=.;
  91.   if prccq*cshoq>0 then BMq = BEq/(PRCCq*CSHOq);
  92.   at4=%mean_year(atq);ceq4= %mean_year(ceqq); seq4= %mean_year(seqq);
  93.   lctq4=%mean_year(lctq); be4=%mean_year(beq);
  94.   if gvkey ne lag3(gvkey) or fyr ne lag3(fyr) then do;
  95.     at4=atq;ceq4=ceqq;seq4=seqq;lctq4=lctq;be4=beq; end;
  96.   at5 = mean(atq,lag(atq),lag2(atq),lag3(atq),lag4(atq));
  97.   lctq5=mean(lctq,lag(lctq),lag2(lctq),lag3(lctq),lag4(lctq));
  98.   if gvkey ne lag4(gvkey) or fyr ne lag4(fyr) then do; at5=at4;lctq5=lctq4;end;
  99.   icaptq=coalesce(icaptq,sum(dlttq,pstkq,mibq,ceqq));
  100.   if missing(saleq) then saleq=saley_q;
  101.   SALE= %ttm(Saleq); if SALE<=0 then SALE=.;
  102.   if gvkey ne lag3(gvkey) or fyr ne lag3(fyr) then SALE=.;
  103.   %do i=1 %to %nwords(&vars_ytd); %let var_ytd=%scan(&vars_ytd,&i,%str(' '));
  104.      if missing(&var_ytd.q) then &var_ytd.q=&var_ytd.y_q;
  105.      drop &var_ytd.y_q &var_ytd.y;
  106.   %end;
  107.   if missing(revtq) then revtq=revty_q;
  108.   if missing(revtq) then revtq=saleq;
  109.   if saleq<=0 then saleq=.;if revtq<=0 then revtq=.;
  110.   if missing(ibq) then ibq=iby_q;
  111.   if missing(ibq) then ibq=niq - xidoq;
  112.   if missing(dvq) then dvq=dvy_q;
  113.   if missing(dvpq) then dvpq=dvpy_q;
  114. run;
  115.  
  116. /*Compute ratios using quarterly data by converting them to TTM values when applicable*/
  117. /*Use mean over the previous 4 quarters for stock accounting variables such as assets, PP&E, etc*/
  118. /*Use TTM values from Compustat Quarterly set whenever available, e.g., epsf12, oeps12, etc*/
  119. /*All per share metrics are adjusted to make them comparable/summable over time*/
  120. /*Price for valuation ratios will be brought in later in the program*/
  121. data __compq3;
  122. set __compq2;
  123. by gvkey fyr fyearq fqtr;
  124.  /* Valuation Ratios*/
  125.     CAPEIq=%ttm(IBq); /*Shiller's P/E*/
  126.     evmq=%mean_year(sum(dlttq,dlcq,mibq,pstkq, prccq*cshoq))/coalesce(%ttm(oibdpq),SALE-%ttm(cogsq)-%ttm(xsgaq)); /*Enterprise Value Multiple*/
  127.     pe_op_basicq=coalesce(oeps12,%ttm(opepsq/ajexq)); /*price-to-operating EPS, excl. EI (basic)*/
  128.     pe_op_dilq=coalesce(oepf12,%ttm(oepsxq/ajexq)); /*price-to-operating EPS, excl. EI (diluted)*/
  129.     pe_exiq=coalesce(epsf12,%ttm(epsfxq/ajexq)); /*price-to-earnings, excl. EI (diluted)*/
  130.     pe_incq=coalesce(epsfi12,%ttm(epsfiq/ajexq)); /*price-to-earnings, incl. EI (diluted)*/
  131.     psq=SALE; /*price-to-sales ratio*/
  132.     opcfq=coalesce(%ttm(oancfy_q),%ttm(ibq)-sum(dif4(actq),-dif4(cheq),-dif4(lctq),dif4(dlcq),dif4(txpq),-%ttm(dpq))); /*operating cash flow*/
  133.     pcfq=opcfq; /*price-to-cash flow*/
  134.     if coalesce(ibadj12,%ttm(ibadjq))>0 then
  135.     dprq=%ttm(sum(dvq,dvpq))/coalesce(ibadj12,%ttm(ibadjq)); /*dividend payout ratio, cash dividends+preferred dividends*/
  136.  /*Profitability Ratios and Rates of Return*/
  137.     npmq=%ttm(ibq)/SALE;  /*net profit margin*/
  138.     opmbdq=coalesce(%ttm(oibdpq),SALE-%ttm(xoprq))/SALE;  /*operating profit margin before depreciation*/
  139.     opmadq=coalesce(%ttm(oiadpq),%ttm(oibdpq-dpq),SALE-%ttm(xoprq)-%ttm(dpq))/SALE;/*operating profit margin after depreciation*/                                
  140.     gpmq=%ttm(revtq-cogsq)/SALE; /*gross profit margin*/                                  
  141.     ptpmq=coalesce(%ttm(piq),%ttm(oiadpq)-%ttm(xintq)+%ttm(spiq)+%ttm(nopiq))/SALE;  /*pretax profit margin*/                                        
  142.     cfmq=coalesce(%ttm(ibcq+dpcq),%ttm(ibq+dpq))/SALE;  /*cash flow margin*/                                    
  143.     roaq=coalesce(%ttm(oibdpq),SALE-%ttm(xoprq))/lag(at4); /*Return on Assets*/
  144.     roceq=coalesce(%ttm(oiadpq),%ttm(oibdpq)-%ttm(dpq),SALE-%ttm(xoprq)-%ttm(dpq),SALE-%ttm(cogsq)-%ttm(xsgaq)-%ttm(dpq))/lag(%mean_year(dlttq+dlcq+ceqq)); /*Return on Capital Employed*/
  145.     if coalesce(%ttm(piq),%ttm(oiadpq)-%ttm(xintq)+%ttm(spiq)+%ttm(nopiq))>0 then
  146.     efftaxq=%ttm(txtq)/coalesce(%ttm(piq),%ttm(oiadpq)-%ttm(xintq)+%ttm(spiq)+%ttm(nopiq)); /*effective tax rate*/
  147.  
  148.     lagbe4=lag(be4); lagseq4=lag(seq4); lagicapt4=lag(%mean_year(sum(icaptq,TXDITCq,-mibq)));lagppent4=lag(%mean_year(ppentq+actq-lctq));
  149.     lagppent_alt4=lag(%mean_year(ppentq+actq));
  150.  
  151.     if first.gvkey or first.fyr then do; lagbe4=be4;lagseq4=seq4;lagicapt4=%mean_year(sum(icaptq,TXDITCq,-mibq));
  152.     lagppent4=%mean_year(ppentq+actq-lctq);lagppent_alt4=%mean_year(ppentq+actq);end;
  153.     if lagbe4>=0 then roeq=%ttm(ibq)/lagbe4; /*Return on Equity*/                                
  154.     aftret_eqq=coalesce(%ttm(ibcomq),%ttm(ibq-dvpq))/lag(ceq4); /*after tax return on average common equity*/
  155.     if lagicapt4>0 then
  156.     aftret_invcapxq=%ttm(sum(ibq+xintq,miiq))/lagicapt4; /*after tax return on invested capital*/
  157.     aftret_equityq=%ttm(ibq)/lag(seq4); /*after tax return on total stock holder's equity*/
  158.     pretret_noaq=coalesce(%ttm(oiadpq),%ttm(oibdpq-dpq),SALE-%ttm(xoprq)-%ttm(dpq))/lagppent4; /*pretax return on net operating assets*/
  159.     pretret_earnatq=coalesce(%ttm(oiadpq),%ttm(oibdpq-dpq),SALE-%ttm(xoprq)-%ttm(dpq))/lagppent_alt4; /*pretax return on total earning assets*/  
  160.     GProfq=%ttm(revtq-cogsq)/at4;  /*gross profitability as % of total assets*/
  161.   /*Capitalization Ratios*/
  162.     if %mean_year(icaptq)>0 then do;
  163.      equity_invcapq=%mean_year(ceqq)/%mean_year(icaptq);   /*Common Equity as % of invested capital*/
  164.      debt_invcapq=%mean_year(dlttq)/%mean_year(icaptq);    /*Long-term debt as % of invested capital*/
  165.      totdebt_invcapq=%mean_year(dlttq+dlcq)/%mean_year(icaptq);  /*Total Debt as % of invested capital*/
  166.      end;
  167.     capital_ratioq=%mean_year(dlttq)/%mean_year(dlttq+sum(ceqq,pstkq)); /*capitalization ratio*/
  168.   /*Financial Soundness Ratios*/
  169.     int_debtq=%ttm(xintq)/%mean_year(dlttq); /*interest as % of average long-term debt*/
  170.     int_totdebtq=%ttm(xintq)/%mean_year(dlttq+dlcq); /*interest as % of average total debt*/
  171.     cash_ltq=%mean_year(cheq)/%mean_year(ltq); /*Cash balance to Total Liabilities*/
  172.     invt_actq=%mean_year(invtq)/%mean_year(actq); /*inventory as % of current assets*/
  173.     rect_actq=%mean_year(rectq)/%mean_year(actq); /*receivables as % of current assets*/
  174.     debt_atq=%mean_year(dlttq+dlcq)/%mean_year(atq); /*total debt as % of total assets*/
  175.     debt_ebitdaq=%mean_year(dlttq+dlcq)/coalesce(%ttm(oibdpq),SALE-%ttm(cogsq)-%ttm(xsgaq)); /*gross debt to ebitda*/
  176.     short_debtq=%mean_year(dlcq)/%mean_year(dlttq+dlcq); /*short term term as % of total debt*/
  177.     curr_debtq=%mean_year(lctq)/%mean_year(ltq); /*current liabilities as % of total liabilities*/
  178.     lt_debtq=%mean_year(dlttq)/%mean_year(ltq); /*long-term debt as % of total liabilities*/
  179.     profit_lctq=coalesce(%ttm(OIBDPq),SALE-%ttm(xoprq))/%mean_year(lctq); /*profit before D&A to current liabilities*/
  180.     ocf_lctq=opcfq/%mean_year(lctq); /*operating cash flow to current liabilities*/
  181.     if opcfq>0 then fcf_ocfq=(opcfq-%ttm(capxq))/opcfq;/*free cash flow to operating cash flow*/
  182.     cash_debtq=coalesce(%ttm(oancfy_q),%ttm(ibq)-sum(dif4(actq),-dif4(cheq),-dif4(lctq),dif4(dlcq),dif4(txpq),-%ttm(dpq)))/%mean_year(ltq);/*cash flow to debt*/
  183.     lt_ppentq=%mean_year(ltq)/%mean_year(ppentq); /*total liabilities to total tangible assets*/
  184.     if %mean_year(beq)>0 then dltt_beq=%mean_year(dlttq)/%mean_year(beq); /*long-term debt to book equity*/
  185.  /*Solvency ratios*/
  186.     debt_assetsq=%mean_year(ltq)/%mean_year(atq); /*Debt-to-assets*/
  187.     debt_capitalq=%mean_year(apq+sum(dlcq,dlttq))/%mean_year(apq+sum(dlcq,dlttq)+sum(ceqq,pstkq)); /*debt-to-capital*/
  188.     de_ratioq=%mean_year(ltq)/%mean_year(sum(ceqq,pstkq)); /*debt to equity ratio*/
  189.     intcovq=%ttm(xintq+ibq)/%ttm(xintq); /*after tax interest coverage*/
  190.     intcov_ratioq=coalesce(%ttm(oiadpq),SALE-%ttm(cogsq)-%ttm(xsgaq)-%ttm(dpq))/%ttm(xintq); /*interest coverage ratio*/
  191.  /*Liquidity Ratios*/
  192.    if %mean_year(lctq)>0 then do;
  193.     cash_ratioq=%mean_year(cheq)/%mean_year(lctq); /*cash ratio*/                                  
  194.     quick_ratioq=coalesce(%mean_year(actq-invtq), %mean_year(cheq+rectq))/%mean_year(lctq); /*quick ratio (acid test)*/
  195.     curr_ratioq=coalesce(%mean_year(actq),%mean_year(cheq+rectq+invtq))/%mean_year(lctq); /*current ratio*/
  196.    end;
  197.    cash_conversionq=(%mean_year(invtq)/(%ttm(cogsq)/365))+(%mean_year(rectq)/(SALE/365))-(%mean_year(apq)/(%ttm(cogsq)/365)); /*cash conversion cycle*/
  198.    if cash_conversionq<0 then cash_conversionq=.;
  199.  /*Activity/Efficiency Ratios*/
  200.    if %mean_year(invtq)>0 then inv_turnq=%ttm(cogsq)/%mean_year(invtq);  /*inventory turnover*/                    
  201.    if at4>0 then at_turnq=SALE/at4;   /*asset turnover*/  
  202.    if %mean_year(rectq)>0 then rect_turnq=SALE/%mean_year(rectq); /*receivables turnover*/
  203.    if %mean_year(apq)>0 then pay_turnq=(%ttm(cogsq)+dif4(invtq))/%mean_year(apq); /*payables turnover*/
  204.  /*Miscallenous Ratios*/
  205.    if %mean_year(icaptq)>0 then sale_invcapq=SALE/%mean_year(icaptq); /*sale per $ invested capital*/
  206.    if seq4>0 then sale_equityq=SALE/seq4; /*sales per $ total stockholders' equity*/
  207.    if %mean_year(actq-lctq)>=0 then sale_nwcq=SALE/%mean_year(actq-lctq);/*sales per $ working capital*/
  208.    rd_saleq=%ttm(sum(xrdq,0))/SALE; if rd_saleq<0 then rd_saleq=0; /*R&D as % of sales*/
  209.    Accrualq = coalesce(%ttm(oancfy_q-ibq),-sum(dif4(actq),-dif4(cheq),-dif4(lctq),dif4(dlcq),dif4(txpq),-%ttm(dpq)))/at5;
  210.    ocf=ibq-sum(dif(actq),-dif(cheq),-dif(lctq),dif(dlcq),dif(txpq),-dpq);
  211.  
  212.  if gvkey ne lag3(gvkey) or fyr ne lag3(fyr) or sum(%ttm(fqtr)) ne 10 then
  213.    do;
  214.         pe_op_basicq=.; pe_op_dilq=.;pe_exiq=.;pe_incq=.;psq=.;pcfq=.;evmq=.;dprq=.;npmq=.;opmbdq=.;opmadq=.;gpmq=.;ptpmq=.;cfmq=.;intcov_ratioq=.;
  215.         GProfq=.;equity_invcapq=.; debt_invcapq=.;capital_ratioq=.;totdebt_invcapq=.;int_debtq=.;int_totdebtq=.;cash_ltq=.;invt_actq=.;
  216.         rect_actq=.;debt_atq=.;short_debtq=.;curr_debtq=.;lt_debtq=.;profit_lctq=.;ocf_lctq=.;lt_ppentq=.;dltt_beq=.;efftaxq=.;fcf_ocfq=.;
  217.         debt_assetsq=.;debt_capitalq=.;de_ratioq=.;intcovq=.;cash_ratioq=.;quick_ratioq=.;curr_ratioq=.;inv_turnq=.;cash_debtq=.;
  218.         at_turnq=.;rect_turnq=.;pay_turnq=.;sale_invcapq=.;sale_equityq=.;sale_nwcq=.;RD_SALEq=.;Accrualq=.;cash_conversionq=.;debt_ebitdaq=.;
  219.     end;
  220. /*Return on "smth" ratios always use lagged scalers, therefore, more lags are needed*/
  221.   if gvkey ne lag4(gvkey) or fyr ne lag4(fyr) then
  222.    do;
  223.       roaq=.; roeq=.;roceq=.; aftret_eqq=.;aftret_invcapxq=.;aftret_equityq=.;pretret_noaq=.;pretret_earnatq=.;
  224.    end;
  225.      
  226.   keep gvkey fyr fyearq fqtr datadate beq bmq CAPEIq evmq pe_op_basicq pe_op_dilq pe_incq pe_exiq psq pcfq dprq npmq opmbdq opmadq gpmq ptpmq intcov_ratioq
  227.         cfmq roaq roeq roceq aftret_eqq aftret_invcapxq aftret_equityq pretret_noaq pretret_earnatq equity_invcapq  debt_invcapq fcf_ocfq
  228.         totdebt_invcapq int_debtq int_totdebtq cash_ltq invt_actq rect_actq debt_atq short_debtq curr_debtq lt_debtq capital_ratioq
  229.         profit_lctq ocf_lctq lt_ppentq dltt_beq debt_assetsq debt_capitalq de_ratioq intcovq cash_ratioq quick_ratioq curr_ratioq debt_ebitdaq
  230.         inv_turnq CAPEIq at_turnq rect_turnq pay_turnq sale_invcapq sale_equityq sale_nwcq RD_SALEq Accrualq GProfq cash_conversionq
  231.         teqq epsfxq revtq ocf prccq;
  232.    rename datadate=qdate;
  233. run;
  234.  
  235. proc sort data=__compq3 nodupkey; by gvkey qdate fyr; run;
  236. data __compq4; set __compq3; by gvkey qdate; if last.qdate; drop fyr fyearq fqtr; run;
  237. proc sort data=__compq4 nodupkey; by gvkey qdate; run;
  238.  
  239. /*Calculate moving average income before EI over previous 20 quarters (5 years)*/
  240. proc expand data=__compq4 out=__compq4 method=none;
  241.  by gvkey;id qdate;
  242.  convert CAPEIq=CAPEIq/ transformout=(MOVAVE 20 trimleft 12);
  243. quit;
  244.  
  245.  
  246. %populate(inset=__compq4,outset=__compq4,datevar=qdate,idvar=gvkey,forward_max=12);
  247.  
  248. %let aratios=&vars;
  249. %let aratios=%sysfunc(compbl(&aratios.));
  250. %let qratios=%sysfunc(tranwrd(&aratios. %str(),%str( ),%str(q )));
  251. %let nratios=%nwords(&aratios);
  252. /*Merge populated Annual and Quarterly data and always pick the most recently available metric*/
  253. data __comp1;
  254.  merge __compq4;
  255.   by gvkey mdate;
  256.   /* Populate Variables */
  257.    array annratio {&nratios} &aratios;
  258.    array qtrratio {&nratios} &qratios;
  259.    do i=1 to &nratios;
  260.      if not missing(qtrratio(i)) and qdate>adate then annratio(i)=qtrratio(i);
  261.    end;
  262.   /*date when the information becomes public*/
  263.   public_date=intnx("month",mdate,2,"e"); format public_date date9.;
  264.   drop i &qratios;
  265. run;
  266.  
  267. /*Populate Historical SIC codes into monthly frequency*/
  268. %populate(inset=comp.co_industry,outset=sich,datevar=datadate,idvar=gvkey fyr,forward_max=12);
  269. /*Populate Compustat shares outstanding data CSHOQ into monthly frequency, CSHOM is often missing*/
  270. data comp_shares/view=comp_shares; set  comp.co_ifndq;
  271.   where &compcond.;
  272.   keep gvkey datadate cshoq;
  273. run;
  274. %populate(inset=comp_shares,outset=shares_comp,datevar=datadate,idvar=gvkey,forward_max=3);
  275.  
  276. /*Get pricing for primary US common shares from Security Monthly table*/
  277. proc sql;
  278.   create table prc_shares_comp
  279.    as select distinct a.*, b.prc_comp_unadj, b.prc_comp_adj, b.cshom, b.dvrate
  280.   from shares_comp a inner join
  281.    (select distinct gvkey, iid, datadate, prccm as prc_comp_unadj, (prccm/ajexm) as prc_comp_adj, cshom, dvrate from
  282.    comp.secm where tpci='0' and fic='USA' and primiss='P') b
  283.    on a.gvkey=b.gvkey and a.mdate=intnx('month',b.datadate,0,'e');
  284. quit;
  285. proc sort data=prc_shares_comp nodupkey; by gvkey mdate;run;
  286. /*Grab Historical GICS*/
  287. proc sql;
  288.   create view gics
  289.     as select a.gvkey, a.gsector, a.indfrom, a.indthru, b.gicdesc
  290.   from comp.co_hgic a, comp.r_giccd b
  291.   where a.gsector=b.giccd and b.gictype='GSECTOR';
  292. /*Merge in historical SIC from CRSP&Compustat and use S&P GICS; Link with CRSP Permno using CCM*/
  293. create view __comp2
  294.   as select distinct c.lpermno as permno, a.*, coalesce(b.sich, d.siccd) as sic
  295.  from __comp1 a left join sich (where=(consol='C' and popsrc='D')) b
  296.    on a.gvkey=b.gvkey and a.mdate=b.mdate
  297.  inner join
  298.    crsp.ccmxpf_linktable (where=(usedflag=1 and linkprim in ('P','C'))) c
  299.    on a.gvkey=c.gvkey and (c.linkdt<=a.mdate<=c.linkenddt or (c.linkdt<=a.mdate and missing(c.linkenddt)))
  300.  inner join (select distinct permno, siccd, shrcd, min(namedt) as mindate, max(nameenddt) as maxdate
  301.  from crsp.stocknames where shrcd in (10,11) group by permno, shrcd, siccd) d
  302.    on c.lpermno=d.permno and d.mindate<=a.mdate<=d.maxdate;
  303.  
  304. /*Calculate market value using CRSP and Compustat separately as of date when finstatements become available*/
  305. /*Merge in labels for GICS sectors and define S&P 500 members*/
  306. create table __comp3
  307.   as select distinct a.*,
  308.    c.dvrate, abs(b.prc)*b.shrout/1000 as mcap_crsp,
  309.    (c.cshoq*c.prc_comp_unadj) as mcap_comp,
  310.    abs(b.prc) as prc_crsp_unadj, c.prc_comp_unadj,
  311.    (abs(prc)/b.CFACPR) as prc_crsp_adj, c.prc_comp_adj,
  312.    d.gsector, d.gicdesc, not missing(e.gvkeyx) as sp500
  313.  from __comp2 a left join crsp.msf b
  314.    on a.permno=b.permno and a.public_date=intnx('month',b.date,0,'e')
  315.  left join prc_shares_comp c
  316.    on a.gvkey=c.gvkey and a.public_date=c.mdate
  317.  left join gics d
  318.    on a.gvkey=d.gvkey and
  319.       (d.indfrom<=a.public_date<=d.indthru or (d.indfrom<=a.public_date and missing(d.indthru)))
  320.  left join comp.idxcst_his (where=(gvkeyx='000003')) e
  321.    on a.gvkey=e.gvkey and
  322.       (e.from<=a.public_date<=e.thru or (e.from<=a.public_date and missing(e.thru)))
  323.  order by a.gvkey, a.public_date;
  324. quit;
  325.  
  326. proc sort data=__comp3 nodupkey; by gvkey public_date;run;
  327.  
  328. /* ----------- IBES here ------------- */
  329. /*future EPS and annual EPS growth rate from IBES*/
  330. /*proc sort data=ibes.act_epsus (keep=ticker pends pdicity anndats value) out=actuals nodupkey;
  331.   where PDICITY='ANN' and not missing(value);
  332.   by ticker PENDS anndats;
  333. run;*/
  334.  
  335. /*data actuals; set actuals;
  336.  by ticker pends;
  337.   lagpends=lag(pends); lagvalue=lag(value); laganndats=lag(anndats);
  338.   format lagpends date9. laganndats date9.;
  339.   if first.ticker then do; lagpends=intnx('month',pends,-12,'e'); lagvalue=.; laganndats=.;end;
  340. run;*/
  341. /*Prepare IBES file for computing forward 1 year and LTG EPS growth*/
  342. /*proc sql;
  343.   create table eps_growth (where=(not missing(datadate) and not missing(gvkey)))
  344.    as select distinct d.gvkey, a.ticker, b.lagpends as datadate,b.laganndats as current_anndate,
  345.       b.lagvalue as current_actual, a.statpers, a.fpedats as futdate, a.actual as fut_actual,
  346.       a.meanest as fut_eps, a.anndats_act as fut_anndate, c.meanest as ltg_eps
  347.  from ibes.statsum_epsus (where=(fpi='1' and FISCALP='ANN' and CURR_ACT='USD')) a
  348.   left join actuals b
  349.    on a.ticker=b.ticker and a.fpedats=b.pends
  350.   left join ibes.statsum_epsus (where=(fpi='0' and FISCALP='LTG')) c
  351.    on a.ticker=c.ticker and a.statpers=c.statpers
  352.   left join (select distinct gvkey, ibtic from comp.security where not missing(ibtic)) d
  353.    on a.ticker=d.ibtic
  354.  order by a.ticker, datadate, a.statpers;
  355. quit;*/
  356.  
  357. /*data eps_growth; set eps_growth;
  358.   public_date=intnx('month',statpers,0,'e');*/
  359.   /*This is expected EPS growth as of given month*/
  360.   /*futepsgrowth=100*(fut_eps-current_actual)/abs(current_actual);
  361.   format statpers date9. public_date date9.;
  362.   if current_anndate < statpers < fut_anndate or nmiss(current_anndate,fut_anndate) > 0;
  363.  keep gvkey public_date ltg_eps current_actual futepsgrowth;
  364. run;
  365. proc sort data=eps_growth nodupkey; by gvkey public_date;run;*/
  366.  
  367. /*Merge Accounting data with Pricing data and compute valuation ratios*/
  368. /*NB: all prices are as of date t, whereas all accounting data are as of t-2 months*/
  369. /*All P/E ratio variations use adjusted price scaled by adjusted EPS*/
  370. data ratios;
  371.   retain gvkey permno adate qdate public_date;
  372.  merge __comp3;
  373.   by gvkey public_date;
  374.   /*use CRSP data first, if available*/
  375.     mktcap=coalesce(mcap_crsp, mcap_comp);
  376.     price=coalesce(prc_crsp_unadj, prc_comp_unadj);
  377.     capei=(mktcap/capei); /*Shiller's CAPE*/
  378.     if be>0 then ptb=mktcap/be; else ptb=.;/*price-to-book*/
  379.     bm=coalesce(BM,BE/mktcap); if bm<0 then bm=.; /*book-to-market*/
  380.     /*in the definition of trailing PEG ratio in the line below PE_EXI is the adjusted diluted EPS excluding EI, not PE*/
  381.     /*eps3yr_growth=mean(pe_exi/lag12(pe_exi)-1,lag12(pe_exi)/lag24(pe_exi)-1,lag24(pe_exi)/lag36(pe_exi)-1);*//*3-yr past EPS growth*/
  382.     *if eps3yr_growth>0 then
  383.     *PEG_trailing=(prc_comp_adj/pe_exi)/(100*eps3yr_growth); /*trailing PEG Ratio*/
  384.     *if gvkey ne lag36(gvkey) or eps3yr_growth<0 then PEG_trailing=.;
  385.     *pe_op_basic=(prc_comp_adj/pe_op_basic); /*price-to-operating EPS, excl. EI (basic)*/
  386.     *pe_op_dil=(prc_comp_adj/pe_op_dil); /*price-to-operating EPS, excl. EI (diluted)*/
  387.     /*now PE_EXI becomes the actual Price-to-Earnings ratio after adjusted Compustat price is used in the numerator of the ratio*/
  388.     pe_exi=(prc_comp_adj/pe_exi); /*price-to-earnings, excl. EI (diluted)*/
  389.     pe_inc=(prc_comp_adj/pe_inc); /*price-to-earnings, incl. EI (diluted)*/
  390.     ps=(mktcap/ps); /*price-to-sales ratio*/
  391.     pcf=(mktcap/pcf); /*price-to-cash flow ratio*/
  392.     divyield=DVRATE/price; /*dividend yield*/ if divyield<0 then divyield=.;
  393.     /*forward PEG Ratios*/
  394.     /*Assume PEG ratios are negative whenver expected EPS growth is negative*/
  395.     *if sign(pe_exi)=-1 and sign(futepsgrowth)=-1 then PEG_1yrforward=-(pe_exi/futepsgrowth);
  396.     *else PEG_1yrforward=pe_exi/futepsgrowth;
  397.     *if sign(pe_exi)=-1 and sign(ltg_eps)=-1 then PEG_ltgforward=-(pe_exi/ltg_eps);
  398.     *else PEG_ltgforward=pe_exi/ltg_eps;
  399.     /*define FF industries*/
  400.     if sic=0 then sic=.;
  401.     if missing(sic)=0 then %FFI5(sic);
  402.     if missing(sic)=0 then %FFI10(sic);
  403.     if missing(sic)=0 then %FFI12(sic);
  404.     if missing(sic)=0 then %FFI17(sic);
  405.     if missing(sic)=0 then %FFI30(sic);
  406.     if missing(sic)=0 then %FFI38(sic);
  407.     if missing(sic)=0 then %FFI48(sic);
  408.     if missing(sic)=0 then %FFI49(sic);
  409.  
  410.     *ffi&nind._desc=upcase(ffi&nind._desc);
  411.     ffi5_desc=upcase(ffi5_desc);
  412.     ffi10_desc=upcase(ffi10_desc);
  413.     ffi12_desc=upcase(ffi12_desc);
  414.     ffi17_desc=upcase(ffi17_desc);
  415.     ffi30_desc=upcase(ffi30_desc);
  416.     ffi38_desc=upcase(ffi38_desc);
  417.     ffi48_desc=upcase(ffi48_desc);
  418.     ffi49_desc=upcase(ffi49_desc);
  419.  
  420.     /*format all ratios*/
  421.     format %do i=1 %to %nwords(&allvars); %scan(&allvars, &i, %str(' ')) comma7.3 %end;;
  422.     format divyield percent7.4 qdate date9. adate date9.;
  423.    label
  424.     public_date='Date'
  425.     adate='Fiscal year end'
  426.     qdate='Fiscal quarter end'
  427.     sic='Historical SIC code'
  428.     mktcap='Market Capitalization, $mil.'
  429.     ptb='Price/Book'
  430.     bm='Book/Market'
  431.     divyield='Dividend Yield'
  432.     peg_trailing='Trailing P/E to Growth (PEG) ratio'
  433.     PEG_1yrforward='Forward P/E to 1-year Growth (PEG) ratio'
  434.     PEG_ltgforward='Forward P/E to Long-term Growth (PEG) ratio'
  435.     CAPEI='Shillers Cyclically Adjusted P/E Ratio'
  436.     pe_op_basic='Price/Operating Earnings (Basic, Excl. EI)'
  437.     pe_op_dil='Price/Operating Earnings (Diluted, Excl. EI)'
  438.     pe_exi='P/E (Diluted, Excl. EI)'
  439.     pe_inc='P/E (Diluted, Incl. EI)'
  440.     evm='Enterprise Value Multiple'
  441.     ps='Price/Sales'
  442.     pcf='Price/Cash flow'
  443.     dpr='Dividend Payout Ratio'
  444.     npm='Net Profit Margin'
  445.     opmbd='Operating Profit Margin Before Depreciation'
  446.     opmad='Operating Profit Margin After Depreciation'
  447.     gpm='Gross Profit Margin'
  448.     ptpm='Pre-tax Profit Margin'
  449.     cfm='Cash Flow Margin'
  450.     efftax='Effective Tax Rate'
  451.     ROA='Return on Assets'
  452.     ROE='Return on Equity'
  453.     ROCE='Return on Capital Employed'
  454.     aftret_eq='After-tax Return on Average Common Equity'
  455.     aftret_invcapx='After-tax Return on Invested Capital'
  456.     aftret_equity='After-tax Return on Total Stockholders Equity'
  457.     pretret_noa='Pre-tax return on Net Operating Assets'
  458.     pretret_earnat='Pre-tax Return on Total Earning Assets'
  459.     Gprof='Gross Profit/Total Assets'
  460.     equity_invcap='Common Equity/Invested Capital'
  461.     debt_invcap='Long-term Debt/Invested Capital'
  462.     totdebt_invcap='Total Debt/Invested Capital'
  463.     debt_ebitda='Total Debt/EBITDA'
  464.     int_debt='Interest/Average Long-term Debt'
  465.     int_totdebt='Interest/Average Total Debt'
  466.     cash_lt='Cash Balance/Total Liabilities'
  467.     invt_act='Inventory/Current Assets'
  468.     rect_act='Receivables/Current Assets'
  469.     debt_at='Total Debt/Total Assets'
  470.     cash_debt='Cash Flow to Total Liabilities'
  471.     short_debt='Short-Term Debt/Total Debt'
  472.     curr_debt='Current Liabilities/Total Liabilities'
  473.     lt_debt='Long-term Debt/Total Liabilities'
  474.     profit_lct='Profit Before Depreciation/Current Liabilities'
  475.     ocf_lct='Operating CF/Current Liabilities'
  476.     fcf_ocf='Free Cash Flow/Operating Cash Flow'
  477.     capital_ratio='Capitalization Ratio'
  478.     lt_ppent='Total Liabilities/Total Tangible Assets'
  479.     dltt_be='Long-term Debt/Book Equity'
  480.     debt_assets='Total Debt/Total Assets'
  481.     debt_capital='Total Debt/Capital'
  482.     de_ratio='Total Debt/Equity'
  483.     intcov='After-tax Interest Coverage'
  484.     intcov_ratio='Interest Coverage Ratio'
  485.     cash_ratio='Cash Ratio'
  486.     cash_debt='Cash Flow/Total Debt'
  487.     quick_ratio='Quick Ratio (Acid Test)'
  488.     curr_ratio='Current Ratio'
  489.     cash_conversion='Cash Conversion Cycle (Days)'
  490.     inv_turn='Inventory Turnover'
  491.     at_turn='Asset Turnover'
  492.     rect_turn='Receivables Turnover'
  493.     pay_turn='Payables Turnover'
  494.     sale_invcap='Sales/Invested Capital'
  495.     sale_equity='Sales/Stockholders Equity'
  496.     sale_nwc='Sales/Working Capital'
  497.     rd_sale='Research and Development/Sales'
  498.     adv_sale='Avertising Expenses/Sales'
  499.     staff_sale='Labor Expenses/Sales'
  500.     accrual='Accruals/Average Assets';
  501. if mktcap>0;
  502. keep gvkey permno adate qdate public_date &allvars gsector gicdesc sp500
  503. ffi5 ffi5_desc ffi10 ffi10_desc ffi12 ffi12_desc ffi17 ffi17_desc
  504. ffi30 ffi30_desc ffi38 ffi38_desc ffi48 ffi48_desc ffi49 ffi49_desc
  505. teqq epsfxq revtq ocf mktcap prccq;
  506. run;
  507.  
  508. /*Apply Winsorization (instead of truncation) to firm-level ratio*/
  509. /*And do not take a 12-month moving average to smooth the ratio*/
  510. %WINSORIZE (INSET=ratios,OUTSET=ratios,SORTVAR=public_date,
  511.             VARS=ptb PEG_trailing pe_op_basic pe_op_dil pe_exi pe_inc ps pcf PEG_ltgforward
  512.             PEG_1yrforward,PERC1=1,TRIM=0);
  513.  
  514. proc sort data=ratios nodupkey; by gvkey public_date;run;
  515.  
  516. proc sort data=ratios nodupkey out=&ratios_out;
  517. where "&begdate"d<=public_date<="&enddate"d;
  518. by public_date gvkey;run;
  519.  
  520. /*
  521. proc sql;
  522.   drop table actuals, eps_growth, prc_shares_comp, ratios, shares_comp, sich, __comp1, __comp3,
  523.        __compa1, __compa3, __compa4, __compq1, __compq2, __compq3, __compq4;
  524.   drop view comp_shares, gics, __comp2;
  525. quit;
  526. */
  527.  
  528. %mend FINRATIO;
  529.  
  530.  
  531. %MACRO FINRATIO_firm (begdate=, enddate=, sp500=, firmratios=);
  532. %if &sp500=1 %then %let sp500_where=and sp500=1; %else %let sp500_where=and 1;
  533. data &firmratios;
  534. set firm_ratio;
  535. where "&begdate"d<=public_date<="&enddate"d &sp500_where;
  536. run;
  537. %mend FINRATIO_firm;
  538.  
  539. %FINRATIO      (BEGDATE=&uni_begdt, ENDDATE=&uni_enddt, SP500=&uni_sp500, RATIOS_OUT=firm_ratio);
  540. %FINRATIO_firm (BEGDATE=&uni_begdt, ENDDATE=&uni_enddt, SP500=&uni_sp500, FirmRatios=firm_output);
  541.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement