【问题标题】:Creating several windows around a date围绕日期创建多个窗口
【发布时间】:2017-11-21 11:16:31
【问题描述】:

我正在处理一个包含多只股票的数据集,并且我将一个带有事件的数据集合并到它上面(对于股票,每只股票在一段时间内的几个事件)。

现在,对于事件研究,我想创建几个变量作为虚拟变量并创建窗口:-60 到 -11 天、-5 到 -1 天和公告日加 +1 天。 重要的是两件事:

  1. 必须按库存(窗口不应在库存之间结转)
  2. 一个公告/活动日 (ann_day) 不应破坏另一个活动的窗口。

我尝试了以下方法,但它只是给了我一个窗口,并没有考虑到不同的库存和损坏的窗口:

proc sql; 
   create view event_study as 
   select distinct b.ann_date,a.date,a.dayid-b.dayid as event_time, a.stock,a.return
   from Dataset_full as a,Announcements as b 
   where a.dayid-b.dayid between -60 and 11 and a.secid=b.secid
   order by a.stockb.ann_date,event_time; 
quit;

一些信息:公告日是事件 dataset_full 有库存、日期、回报、数量。每个日历/交易日一行。 公告有股票、公告日期和公告信息(每条公告一行) 数据应如下所示:

Stock   Date    Ann_date    flag_minus60_minus11    flag_minus5_minus1  flag_day0_day1
A   1/01/2016           1   
A   2/01/2016           1   
A   3/01/2016               
A   4/01/2016   4/01/2016           1
A   5/01/2016               1
A   6/01/2016               
A   7/01/2016               
A   8/01/2016               
A   9/01/2016               
A   10/01/2016              
A   11/01/2016              
A   12/01/2016              
A   13/01/2016              
A   14/01/2016              
A   15/01/2016              
B   1/01/2016       1       
B   2/01/2016       1       
B   3/01/2016       1       
B   4/01/2016       1       
B   5/01/2016       1       
B   6/01/2016       1       
B   7/01/2016               
B   8/01/2016               
B   9/01/2016               
B   10/01/2016              
B   11/01/2016          1   
B   12/01/2016          1   
B   13/01/2016          1   
B   14/01/2016          1   
B   15/01/2016          1   
B   16/01/2016  16/01/2016          1
B   17/01/2016              1
B   18/01/2016          1   
B   19/01/2016          1   
B   20/01/2016  20/01/2016          1
B   21/01/2016              1
B   22/01/2016              
B   23/01/2016              
B   24/01/2016              
B   25/01/2016              

【问题讨论】:

    标签: sas time-series


    【解决方案1】:

    马博:

    这是一些示例数据和 SQL。当您检查输出时,我想您会看到“被破坏”的信息——即在标记时间范围内有多个未来公告的日期。

    相对于事件日期标记交易日期的问题是内部连接。必须对正在计算的每个标志执行内连接,并且内连接需要与交易数据保持连接以获得您的“想要”。

    data trading;
      do group = 1 to 4;
        do date = today()-1000 to today(); format date yymmdd10.;
          output;
        end;
      end;
    run;
    
    data announcement;
      do group = 1 to 4;
        do date = today()-1000 to today(); format date yymmdd10.;
          if ranuni(123) < 0.01 then output;
        end;
      end;
    run;
    
    proc sql;
      create table trading_pre_announce_flagged as
      select 
        trading.*
      , announcement.date as annouce_date
      , case when P0.date is not null then 1 else . end as P0_flag label="Announcement was today or yesterday"
      , case when P1.date is not null then 1 else . end as P1_flag label="Announcement in 1 to 5 days"
      , case when P2.date is not null then 1 else . end as P2_flag label="Announcement in 11 to 60 days"
      , case when P2.date is not null then P2.adate else . end as P2_date label="Date of Announcement in 11 to 60 days" format=yymmdd10.
    
      from
        trading
      left join 
        announcement 
        on announcement.date = trading.date and announcement.group = trading.group
      left join 
        ( select trading.group, trading.date 
          from trading 
          inner join 
          announcement 
          on    announcement.group = trading.group 
            and announcement.date - trading.date between -1 and 0
        ) as P0
        on P0.date = trading.date and P0.group = trading.group
      left join 
        ( select trading.group, trading.date 
          from trading 
          inner join 
          announcement 
          on    announcement.group = trading.group 
            and announcement.date - trading.date between 1 and 5
        ) as P1
        on P1.date = trading.date and P1.group = trading.group
      left join 
        ( select trading.group, trading.date, announcement.date as adate
          from trading 
          inner join 
          announcement 
          on    announcement.group = trading.group 
          where announcement.date - trading.date between 11 and 60
        ) as P2
        on P2.date = trading.date and P2.group = trading.group
      order
        by trading.group, trading.date
      ;
    quit;
    

    在某些时候(虽然找不到)OP 提到处理约 750 家公司和 500 个整体事件,并且 SQL 解决方案似乎运行时间很长。

    另一种选择是数据步。

    500 个事件是一个足够小的基数,其中组和日期数组可用于存储事件以供查找。排序事件的智能索引跟踪可用于进行最小扫描以评估规则和应用条件标志。

    例如:

    data trading;
      do group = 1 to 700;
        do date = today()-1000 to today(); format date yymmdd10.;
          output;
        end;
      end;
    run;
    
    data announcement;
      do eventid = 1 to 500;
        group = ceil(700*ranuni(123));
        date = (today()-1000) + ceil(1000*ranuni(123)); format date yymmdd10.;
        if mod(eventid,20) = 1 then do;
          output;
          eventid+1;
          date = date + 30 + floor(100*ranuni(123));
          output;
          eventid+1;
          date = date + 30 + floor(100*ranuni(123));
        end;
        output;
      end;
    run;
    
    proc sort data=announcement;
      by group date;
    run;
    
    data _null_;
      if 0 then set announcement nobs=nobs;
      call symputx ('top', nobs+1);
    run;
    
    data marked_trading;
      array e_group(0:&TOP) _temporary_;
      array e_date (0:&TOP) _temporary_;
    
      * load event array;
      do _n_ = 1 by 1 until (last_announcement);
        set announcement end=last_announcement;
        e_group(_n_) = group;
        e_date(_n_) = date;
    
        eix0 = 1;
        eix1 = 1;
      end;
    
      e_group(0) = 0; * sentinel;
      e_group(_n_) = 1e9; *sentinel;
    
      * evaluate flagging criteria for each trade group date;
      do _n_ = 1 by 1 until (last_trading);
        set trading end=last_trading;
        by group;
        if first.group then do;
          * discover indices of events associated with the group;
          do eix0 = eix0 by 1 while (e_group(eix0) < group); end;
          do eix1 = eix0 by 1 while (e_group(eix1) = group); end; eix1 = eix1 - 1;
          eix_group = e_group(eix0);
        end;
    
        p3_flag = .; p2_flag = .; p1_flag = .;
        if group = eix_group then do;
          * NOTE: bounds are evaluated only at loop initialization;
          * evaluate events for flagging a trade;
          do ix = eix0 to eix1;
            days_to_event = e_date(ix) - date;
    
            if not p3_flag then if 11 <= days_to_event <= 60 then p3_flag = 1;
            if not p2_flag then if  1 <= days_to_event <= 5  then p2_flag = 1;
            if not p1_flag then if -1 <= days_to_event <= 0  then p1_flag = 1;
    
            if days_to_event <= -1 then eix0 = ix+1; * update when applicability exhausted;
          end;
        end;
    
        output;
      end;
    
      keep group date p:;
    
      stop;
    run;
    

    【讨论】:

    • 是的,您可以使用数据步。在 n = 1 时,将事件组和日期加载到两个数组中,并评估每个交易行的所有事件的标志条件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多