【问题标题】:SAS: Calculating rolling 6-month skewness from daily returnsSAS:根据每日回报计算滚动 6 个月的偏度
【发布时间】:2018-06-23 13:13:29
【问题描述】:

我正在尝试解决 SAS 中的以下问题。

我有几只股票的每日收益数据。这是我的数据的样子(简化):

PERMNO  DATE        RETURN
10078   2010JAN02   0.0500
10104   2010JAN02   -0.0190
10107   2010JAN02   0.0020
10078   2010JAN03   0.0040
10104   2010JAN03   -0.0400
10107   2010JAN03   0.0500
...       ...        ...
10078   2015JAN02   -0.0190
10104   2015JAN02   0.0100
10107   2015JAN02   0.0700
10078   2015JAN05   0.0500
10104   2010JAN03   -0.0190
10107   2010JAN03   0.0020

PERMNO 标识股票,DATE 标识日期(yyyymmmdd),RETURN 是每日股票收益。 我仅针对三只股票(10078、10104、10107)简化了此示例。

目标:我正在尝试计算给定月份 t 中每只股票 i 的滚动偏度。 我想使用前 6 个月(即 t-6 到 t-1 个月)的每日收益数据来计算每只股票的月度偏度度量。因此,例如,对于股票2010 年 7 月,我希望该月的偏度度量基于 2010 年 1 月至 2010 年 6 月的每日回报。

我希望输出数据包括该月的 PERMNO、月份 ID 和每月偏度度量(基于前 6 个月的数据)。这是一张图片来说明我想要的输出:

PERMNO  DATE        6MONTH_SKEWNESS
10078   2010JUL30   0.7257
10104   2010JUL30   -0.7056
10107   2010JUL30   -0.6781
10078   2010AUG31   0.9999
10104   2010AUG31   -0.6719
10107   2010AUG31   -0.7056
...    ...            ...
10078   2015JUL30   -0.1651
10104   2015JUL30   0.1056
10107   2015JUL30   0.6181
10078   2015AUG31   -0.8886
10104   2015AUG31   0.6119
10107   2015AUG31   0.1056

我已经在网上广泛搜索并亲自尝试过,但我觉得真的被这个问题困住了。提前感谢任何能够以任何方式提供帮助的人。

更新:这是我正在使用的修改后的代码。非常感谢 user667489。

/*Join on the previous 6 months of data for each stock*/
proc sql;
create view rolling as
  select 
    a.PERMNO, /* PERMNO is the variable that identifies a stock */
    a.DATE as MONYR_A label="", /* DATE is a date variable for each daily return */
    b.DATE as MONYR_B label="",
    b.RET /* RET is the variable containing daily returns */
  from Dsex3 a left join Dsex3 b /* Dsex3 is the dataset that contains the identifiers for stocks and their daily returns */  
    on      a.PERMNO = b.PERMNO 
        and 1 <= intck('month',b.date,a.date) <= 6
  group by a.PERMNO, MONYR_A
  having count(*) >= 6 /*Only calculate skewness if we have at least 6 months of data*/
  order by a.PERMNO desc,MONYR_A,MONYR_B;
quit;


/*Calculate the skewness for the previous 6 months worth of data*/
ods listing close;
ods output moments=skewness_summary(
  keep = PERMNO MONYR_A label1 nvalue1
  where=(label1='Skewness')
  rename = (nvalue1 = skewness_6mth)
);
proc univariate data = rolling;
  var RET;
  by descending PERMNO MONYR_A;
run;
ods listing;

【问题讨论】:

  • 那么你尝试了什么?
  • 我不认为我尝试创建的任何代码都接近所需。我面临的主要障碍是我无法弄清楚如何计算每天的滚动偏度度量数据,并将其作为每月的输出。并使用所需的时间窗口(前 6 个月)执行此操作。
  • 您有 SAS/ETS 许可吗?如果是这样,请查看 PROC EXPAND。发布您使用的代码,以便我们知道您尝试了哪些方法,并且因为 SO 不是代码编写服务。

标签: sql sas statistics


【解决方案1】:

如果您没有 SAS/ETS,您可以尝试以下方法:

/*Generate some dummy data from the sashelp area*/
proc summary data = sashelp.prdsal2 nway;
  var ACTUAL;
  class COUNTRY STATE PRODUCT MONYR;
  output out = prdsal2(drop = _:) sum=;
run;

/*Join on the previous 6 months of data for each product*/
proc sql;
create view rolling as
  select 
    a.COUNTRY, 
    a.STATE, 
    a.PRODUCT, 
    a.MONYR as MONYR_A label="", 
    b.MONYR as MONYR_B label="", 
    b.ACTUAL
  from prdsal2 a left join prdsal2 b   
    on      a.COUNTRY = b.COUNTRY 
        and a.STATE   = b.STATE 
        and a.PRODUCT = b.PRODUCT
        and 1 <= intck('month',b.MONYR,a.MONYR) <= 6
  group by a.COUNTRY,a.STATE,a.PRODUCT,MONYR_A
  having count(*) >= 6 /*Only calculate skewness if we have at least 6 months of data*/
  order by a.COUNTRY desc,a.STATE,a.PRODUCT,MONYR_A,MONYR_B;
quit;

/*Calculate the skewness for the previous 6 months worth of data*/
ods listing close;
ods output moments=skewness_summary(
  keep = COUNTRY STATE PRODUCT MONYR_A label1 nvalue1 
  where=(label1='Skewness')
  rename = (nvalue1 = skewness_6mth)
);
proc univariate data = rolling;
  var ACTUAL;
  by descending COUNTRY STATE PRODUCT MONYR_A;
run;
ods listing;

我发现 SAS 有一个实际的 skewness 函数,可以直接为变量列表计算它,所以这里也有一个数据步骤方法:

/*Data step approach, using the skewness function*/
data skewness_summary2;
do _n_ = 1 by 1 until(last.MONYR_A);
  set rolling(keep = COUNTRY STATE PRODUCT MONYR_A ACTUAL);
  by descending COUNTRY STATE PRODUCT MONYR_A;
  skewness_6mth = skewness(ACTUAL,lag1(ACTUAL),lag2(ACTUAL),lag3(ACTUAL),lag4(ACTUAL),lag5(ACTUAL));
  if _n_ >= 6 then output;
end;
run;

data step 方法似乎比使用 proc 单变量要快一些,可能是因为 proc 也在计算所有其他时刻。

【讨论】:

  • 非常感谢您的帮助。我为我的数据集修改了 proc 单变量方法代码(根据变量和表名),它似乎完全符合我的要求。唯一的问题是,该代码会计算可用数据少于 6 个月的股票的偏度度量。出于某种原因,行:有 count(*) >= 6 似乎没有按预期工作。就数据步法而言,它确实似乎更快。有没有办法修改该代码以计算每月输出的每日数据的偏度(如在 proc 单变量方法中)?
  • 如果您设置一个哈希对象来跟踪滚动窗口中的条目,则可以执行类似的操作。我建议你试一试。
猜你喜欢
  • 2019-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
相关资源
最近更新 更多