楼主: deem
6059 3

[程序分享] 事件研究[sas code] [推广有奖]

  • 2关注
  • 43粉丝

学科带头人

51%

还不是VIP/贵宾

-

威望
0
论坛币
7022 个
通用积分
1027.0870
学术水平
215 点
热心指数
237 点
信用等级
205 点
经验
71652 点
帖子
979
精华
0
在线时间
2998 小时
注册时间
2009-7-30
最后登录
2024-4-9

楼主
deem 学生认证  发表于 2017-8-16 03:48:36 |只看作者 |坛友微信交流群|倒序 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
分享一个关于盈余公告事件的SAS code:利用国泰安数据, Follow Dellavigna, S., & Pollet, J. M. (2009) 方法。

这里完成了事件研究数据处理的工作,并计算的相关变量。但是并没有做之后的回归,回归分析我是在Stata里面做的,sas在回归结果的输出、多维固定效应回归方面没有Stata成熟。






  1. /* 用中国A股数据复制 Dellavigna, S., & Pollet, J. M. (2009).
  2. Investor inattention and friday earnings announcements.
  3. The Journal of Finance, 64(2), 709–749. */


  4. /*用到的数据集,来自CSMAR:
  5.         IAR_Rept:盈余公告日期
  6.         Trd_Index:指数交易数据
  7.         dsf:个股交易数据
  8.         af_forecast:分析师预测数据
  9.         af_actual:实际盈余
  10.         Stk_mkt_thrfacday:日度三因子数据 */

  11. * 输入数据和输出数据;
  12. libname csmar ( "F:\CSMAR\AF"  "F:\CSMAR\FAnn"  "F:\CSMAR\TR" );
  13. libname temp "C:\Users\wang123\Desktop\temp";


  14. * 盈余公告日期,2007-2015年年报 ;
  15. data FAnn (drop=Reptyp label='盈余公告日期(只包括2006-2015年年报)');
  16.         set csmar.IAR_Rept (keep=stkcd accper Annodt Reptyp
  17.                 where=(Reptyp=4 and '01Jan2007'd<=accper<='31Dec2015'd));
  18.         run;

  19. * 建立交易日期的索引,‘2006-01-04’标记为1,下一个交易日标记为2,以此类推 ;
  20. data tr_calendar (label='构建交易日历:将交易日和日历日建立1-1对应' drop=indexcd);
  21.          set csmar.Trd_Index (where=(indexcd=1 and '01Jan2005'd<=Trddt<='31Dec2016'd)
  22.                                                  keep=Trddt indexcd);
  23. run;

  24. proc sort data=tr_calendar; by Trddt; run;

  25. data tr_calendar;
  26.         set tr_calendar;
  27.         tr_index+1;
  28.         run;

  29. * 确定事件日;
  30. * 如果盈余公告日是交易日日,以盈余公告日作为事件日;
  31.   如果盈余公告日在非交易日期,则取下一个交易日期为事件日,如果下一个交易日发生距公告日不超过5天 ;
  32. proc sql;  /* cost 53 secs */
  33.         create table evt_date as
  34.         select a.stkcd, a.accper, a.annodt, b.trddt, b.tr_index from fann a
  35.                 left join tr_calendar b
  36.         on a.annodt<=b.trddt<=a.annodt+5
  37.         group by a.stkcd, a.annodt
  38.         having b.trddt-a.annodt=min(b.trddt-a.annodt);
  39.         quit;

  40. data evt_date (label='事件时期数据');
  41.         set evt_date;
  42.         rename Trddt=evtdate;
  43.         label  
  44.                 Stkcd='股票代码'
  45.                 Trddt='事件日期'
  46.                 Accper='会计截止日期'
  47.                 tr_index='自2005年以来第i个交易日'
  48.                 Annodt='报告公布日期';
  49. run;

  50. * 日度股票交易数据,剔除B股数据 ;
  51. data dsf (drop=Markettype label='日各股交易数据');
  52.         set csmar.dsf (keep=stkcd Trddt Clsprc Dretwd Markettype
  53.                 where=('01Jan2005'd<=Trddt<='31Dec2016'd and Markettype in (1,4,16) and
  54.                                 nmiss(stkcd, Trddt, Clsprc, Dretwd, Markettype)=0 and
  55.                                 dretwd <0.11 and dretwd >-0.11));
  56.         label
  57.                 stkcd="证券代码"
  58.                 Trddt="交易日期"
  59.                 Clsprc="日收盘价"
  60.                 Dretwd="考虑现金红利再投资的日个股回报率";
  61.         run;


  62. * 分析师预测数据过滤,形成公司-年-分析师数据:
  63.         (1)只保留盈余公告日最近12个月的盈利预测,并且
  64.         (2)如果一个分析师有多项预测,则仅保留最近的一次预测 ;
  65. proc sql;
  66.         create table af_forecast as
  67.         select a.stkcd "股票代码", a.Fenddt "会计截止日期", a.Feps "EPS预测"
  68.                 from csmar.af_forecast(where=('01Jan2006'd<=Fenddt<='31Dec2015'd)) a
  69.         inner join evt_date b
  70.         on a.stkcd=b.stkcd and a.fenddt=b.accper and
  71.                 intnx('month', b.Annodt, -12, 'B')<a.Rptdt<b.Annodt
  72.         where nmiss(a.stkcd, a.Fenddt, a.Feps)=0
  73.         group by a.stkcd, a.Fenddt, a.AnanmID
  74.                 having a.Rptdt=max(a.Rptdt);
  75. quit;


  76. * EPS一致预测(EPS consensus forecast),公司-年数据;
  77. proc sql;
  78.         create table eps_cons as  
  79.         select stkcd, Fenddt, median(Feps) as eps_cons from af_forecast
  80.                 group by stkcd, Fenddt;
  81.         quit;


  82. data af_actual (label='实际公告的EPS');
  83.         set csmar.af_actual (keep= stkcd Ddate Meps
  84.                 where=('01Jan2006'd<=ddate<='31Dec2015'd));
  85.         run;

  86. * 盈余公告日前5个交易日收盘价,作为SUE的分母;
  87. proc sql;
  88.         create table prc as
  89.         select a.stkcd, a.accper, b.Clsprc as prc '基准收盘价'
  90.         from evt_date a
  91.                 inner join Tr_calendar c
  92.         on a.tr_index-5=c.tr_index   
  93.                 inner join dsf b
  94.         on a.stkcd=b.stkcd and b.Trddt=c.Trddt;
  95.         quit;

  96. * 盈余惊喜(earnings surprise);
  97. proc sql;
  98.         create table sue as
  99.         select a.stkcd, a.fenddt, (a.eps_cons-b.Meps)/c.prc as sue "盈余惊喜" from eps_cons a
  100.                 inner join af_actual b
  101.         on a.stkcd=b.stkcd and a.fenddt=b.ddate
  102.                 inner join prc c
  103.         on a.stkcd=c.stkcd and a.fenddt=c.Accper
  104.         where not missing(calculated sue);
  105.         quit;


  106. * 事件研究估计窗口选择,取[-280, -34];
  107. proc sql;
  108.         create table pre_event as
  109.         select a.stkcd, a.accper, b.Dretwd,
  110.                    d.RiskPremium1 as rm, d.SMB1 as smb, d.HML1 as hml from evt_date a
  111.         left join tr_calendar c
  112.                 on a.tr_index-280 <=c.tr_index<=a.tr_index -34
  113.         left join dsf b
  114.                 on b.Trddt=c.Trddt and b.stkcd=a.stkcd
  115.         left join csmar.Stk_mkt_thrfacday (keep=TradingDate RiskPremium1 SMB1 HML1 MarkettypeID   
  116.                                                                            where=(MarkettypeID='P9709')) d
  117.                 on b.Trddt=d.TradingDate
  118.         where nmiss(Dretwd, rm, smb, hml)=0
  119.         order by stkcd, accper;
  120. quit;


  121. /* 对每个事件,计算三因子模型的因子载荷 */
  122. proc printto log=junk; run;
  123. proc reg data=pre_event noprint outest=ff_est edf;
  124.         by stkcd accper;
  125.         model Dretwd = rm smb hml;
  126.         quit;
  127. proc printto; run;

  128. data ff_est;
  129.         set ff_est;
  130.         obs=_EDF_+_P_;
  131.         keep stkcd accper Intercept rm smb hml obs _RMSE_;
  132.         if obs>120;                        /* 要求估计窗口的交易日期至少达到120天 */
  133.         label Intercept="截距项估计值"
  134.                   rm="市场因子系数"
  135.                   smb="市值因子系数"
  136.                   hml="价值因子系数"
  137.                   obs="估计所用样本数目"
  138.                   _RMSE_="标准误(se)";
  139.         run;


  140. * 利用事件前窗口估计所得系数,建立基准资产组合的收益率
  141.         估计[0,75]的AR, CAR, BHAR;
  142. proc sql;
  143. create table post_event as
  144.     select a.stkcd, a.accper, a.annodt, a.evtdate,
  145.                    c.tr_index-a.tr_index as re_date "相对于事件日的相对交易日", b.Dretwd,
  146.                    e.Intercept+e.rm*d.RiskPremium1+e.smb*d.SMB1+e.hml*d.HML1
  147.                    as ret_bench "由三因子模型确定的基准收益率" from evt_date a
  148.         left join tr_calendar c
  149.                 on a.tr_index <=c.tr_index<=a.tr_index +75
  150.         left join dsf b
  151.                 on b.Trddt=c.Trddt and b.stkcd=a.stkcd
  152.         left join csmar.Stk_mkt_thrfacday (keep=TradingDate RiskPremium1 SMB1 HML1 MarkettypeID   
  153.                                                                            where=(MarkettypeID='P9709')) d
  154.                 on b.Trddt=d.TradingDate
  155.         left join ff_est e
  156.                 on a.stkcd=e.stkcd and a.accper=e.accper
  157.         where nmiss(Dretwd, calculated ret_bench)=0
  158.         order by stkcd, accper, re_date;
  159. quit;

  160. data evt_stat (keep=stkcd accper re_date bhar label='时间研究所得的异常收益,个股层面');
  161.         set post_event;
  162.         by stkcd accper;
  163.         ar=Dretwd-ret_bench;
  164.         retain cumret cumbenchret car;
  165.         cumret=cumret*(1+Dretwd);
  166.         cumbenchret=cumbenchret*(1+ret_bench);
  167.         car=car+ar;
  168.         if first.accper then do;
  169.                 car=ar;
  170.                 cumret=1+Dretwd;
  171.                 cumbenchret=1+ret_bench;
  172.         end;
  173.         bhar=cumret-cumbenchret;
  174. run;


  175. data evt_car (label="股价的短期和长期反应"
  176.                            where=(nmiss(bhar_s, bhar_all)=0));
  177.         merge evt_stat (rename=(bhar=bhar_s) where=(re_date=1))
  178.                   evt_stat (rename=(bhar=bhar_all) where=(re_date=75));
  179.         by stkcd accper;
  180.         run;

  181. data evt_car;
  182.         set evt_car;
  183.         bhar_l=(bhar_all+1)/(bhar_s+1)-1;
  184.         label bhar_s="股价的短期反应BHAR[0, 1]"
  185.           bhar_all="股价的全部反应[0,75]"
  186.                   bhar_l="股价的短期反应BHAR[2, 75]";
  187.         run;

  188. * 和原文不同,我们对比在周五、周六(我们样本中周日没有公告)相对于周内公告的情况
  189.         因为美国在周末几乎没有公告,国内周六公告仍然较多;
  190. proc sql;
  191.         create table evt_car as
  192.         select a.*, weekday(b.Annodt)-1 as dayinweek "用1-7代指周一至周日",
  193.                 weekday(b.Annodt) in (1, 6, 7) as weekend "周末公告的虚拟变量",
  194.                 c.sue from evt_car a
  195.         inner join fann b on a.stkcd=b.stkcd and a.accper=b.accper
  196.         inner join sue c on a.stkcd=c.stkcd and a.accper=c.fenddt;
  197. quit;

  198. proc freq data=evt_car;
  199.         tables dayinweek  accper*weekend / nopercent nocol norow nocum;
  200. run;


  201. * 在每年,分别对“周末公告组”和“周内公告组”按照盈余惊喜从小到大分成10组;
  202. proc sort data=evt_car; by accper weekend; run;

  203. proc rank data=evt_car groups=10 out=car_by_sue;
  204.         by accper weekend;
  205.         var sue;
  206.         ranks sue_rank;
  207.         run;

  208. data car_by_sue (label='按照SUE分组的盈余公告异常收益');
  209.         set car_by_sue;
  210.         sue_rank+1;
  211.         run;

  212. proc sql;
  213.         create table caar as
  214.         select weekend, sue_rank "SUE组合,10为盈余最高",
  215.                 mean(bhar_s) as bhaar_s "每组平均BHAR[0,1]",
  216.                 mean(bhar_l) as bhaar_l "每组平均BHAR[2,75]",
  217.                 mean(bhar_all) as bhaar_all "每组平均BHAR[0,75]",
  218.                 mean(sue) as sue_avg "每组平均SUE"
  219.         from car_by_sue
  220.         group by weekend, sue_rank;
  221.         quit;


  222. * 画图pp721-722;

  223. proc sgplot data=caar;
  224.         series x=sue_rank y=bhaar_s / group=weekend;
  225.         refline 0 / axis=x;
  226. run;

  227. proc sgplot data=caar;
  228.         series x=sue_rank y=bhaar_l / group=weekend;
  229. run;

  230. proc sgplot data=caar;
  231.         series x=sue_avg y=bhaar_l / group=weekend;
  232. run;
复制代码





二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝


已有 1 人评分热心指数 收起 理由
eijuhz + 2 鼓励积极发帖讨论

总评分: 热心指数 + 2   查看全部评分

沙发
liudavid666 学生认证  发表于 2018-1-22 14:10:27 |只看作者 |坛友微信交流群

使用道具

藤椅
水晶之毒 发表于 2019-4-2 19:06:08 |只看作者 |坛友微信交流群
41行到48行的proc sql为什么没有from指令呀?
有点儿看不懂。
a b的数据集是不是都没有标示出来

使用道具

github上抄来的吧

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-24 22:18