Sql SAS:根据每日收益计算滚动6个月的偏斜度
我正在尝试解决SAS中的以下问题 我有几只股票的每日收益数据。这就是我的数据的简化形式:Sql SAS:根据每日收益计算滚动6个月的偏斜度,sql,sas,statistics,Sql,Sas,Statistics,我正在尝试解决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 ... ...
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表示日期YYYYMMDD,RETURN表示每日股票回报。
我简化了这个例子,只针对三只股票100781010410107
目标:我试图计算给定月份t内每种股票的滚动偏度。
我想使用前6个月,即t-6到t-1个月的每日收益数据,计算每个股票的月度偏度。因此,对于2010年7月的股票,我希望该月的偏度度量基于其2010年1月至2010年6月的每日收益
我希望输出数据包括PERMNO、month 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
我已经在网上搜索了很多次,自己也试过了,但我觉得自己真的被困在这个问题上了。提前感谢任何能够以任何方式提供帮助的人
更新:这是我正在使用的修改过的代码。非常感谢用户667489
/*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;
如果您没有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;
数据步进法似乎比使用proc单变量法快一点,可能是因为proc也在计算所有其他时刻。那么您尝试了什么?我认为我尝试创建的代码都不符合需要。我面临的主要障碍是我无法计算出如何从每日数据计算滚动偏斜度度量,并将其作为每月的输出。并在前6个月使用所需的时间窗口执行此操作。您是否拥有SAS/ETS许可证?如果是这样,请查看PROC EXPAND。张贴您使用的代码,以便我们了解您尝试过的方法,因为so不是代码编写服务。非常感谢您的帮助。我根据数据集的变量和表名修改了proc单变量方法代码,它似乎完全符合我的要求。唯一的问题是,该代码为可用数据少于6个月的股票计算偏度度量。由于某些原因,行:having count*>=6似乎无法按预期工作。就数据步方法而言,它确实看起来更快。是否有一种方法可以修改该代码,以按照proc单变量方法计算每月输出的每日数据的偏度?如果您设置一个哈希对象来跟踪滚动窗口中的条目,则可以这样做。我建议你试一试。
/*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;