编辑:我正在研究解决方案,到目前为止一直非常成功。我将在完成并完全运行后立即将其发布以供将来参考。
我正在研究股票回报,并且一直在思考这个问题。我仍然是SAS的新手,这对我来说特别具有挑战性。
我有以下数据集(简化)。
PERMNO DATE RETURN
10078 1995JAN02 0.012000
10104 1995JAN02 0.050000
10107 1995JAN02 -0.019000
10078 1995JAN03 0.002000
10104 1995JAN03 0.004000
10107 1995JAN03 -0.009000
...
10078 1996JAN02 -0.011000
10104 1996JAN02 -0.020000
10107 1996JAN02 0.010000
...
10078 2013JAN03 0.050000
10104 2013JAN03 0.012000
10107 2013JAN03 -0.034000
PERMNO
标识一只股票,DATE
标识一个日期(yyyymmmdd),RETURN
是每日股票回报。
我仅针对三只股票(10078,10104,10107)简化了这个例子。
我的目标是在三个不同的股票之间建立每日相关矩阵,并将一年观察窗口(大约252个过去观察值)输出到日常文件中。
鉴于我的数据集,这应该从1996JAN03
开始(粗略地)。因此,第一天它应该计算所有不同1995JAN02
的{{1}}和1996JAN02
之间所有观察值之间的相关系数(所以PROC CORR)。即然后我应该能够输出以下矩阵
PERMNO
第二天 10078 10104 10107
10078 1 0.1 0.3
10104 0.1 1 0.2
10107 0.3 0.2 1
,我应该能够使用1996JAN04
和1995JAN03
之间的观察输出相同的矩阵。重要的是,最终过程能够处理1996JAN03
中的不匹配数据集。即如果一只股票只有DATE
之后的价格,那么它应该只使用这些日期,如果其中一只股票没有1995JAN05
的记录,它应该能够忽略该观察和使用只有剩下的“匹配”。
我的问题与此Calculating rolling correlations in SAS非常相似,但我的数据并未组织为矩阵。我很想应用建议的方法(仍在研究它)但我必须将我的数据“转换”成矩阵 - 如果这是最有效的方式,我愿意这样做(但我需要帮助我真的不知道怎么做,虽然我可以描述预期的输出。)
(如果您有解决方案,请随意跳过以下部分) 我曾想过要解决这个问题(但尚未转换为SAS代码)是(假设有n股):
1995SET05
的数量(可通过PROC SQL实现); PERMNO
); 1996JAN02
,在开始日期之后获取该PERMNO的日期列表(可能通过PROC SQL); PERMNO
,迭代剩余的股票(因为输出是三角矩阵,我可以转到n - 1 - j剩余股票,其中j是从1到1的当前股票n)并使用return1和return2创建一个表,其中包含(当前日期 - 1)和(当前日期 - 253个观察值)之间的匹配日期; DATE
。然而,这是MATLAB-y或VBA-y,它们是我熟悉的语言,当然也不是SAS中最有效的方法。
我事先感谢你的帮助。
答案 0 :(得分:0)
感谢@Joe和这个paper on calculating correlations with PROC EXPAND的ETS指针,我无法达到初始目标但是非常接近它 - 我可以输出如下数据集(取出一些字段用于简化):
date permno1 permno2 ret1 ret2 rho
1996JAN02 10078 10104 0.01 0.02 0.34
要了解有关PROC EXPAND的更多信息,我建议使用以下paper。
首先,我得到表中所有现有permno
的列表,然后使用宏迭代它们。然后我将初始表中的所有返回值从两个permnos中提取到两个表(company1和company2)中,然后完全连接这些表。对于两家公司都没有退货的日期,记录将被删除。对于两只股票中只有一只股票被交易的日期,因为该观察对于计算任何一天两只股票之间的相关性是无用的。然后我通过PROC EXPAND应用相关公式,通过计算几个具有必要计算的新字段(将很快更新,并提供更好的解释)。拥有所有必要的字段,我计算rho,将结果数据集合并为一个全方位的数据集并循环到下一个公司。
这个代码每个公司大约需要2分钟,因为有大约970家公司需要一天才能完全运行 - 但它确实有效!如果您对此代码有任何意见,我将非常乐意听到它们。
proc sql noprint;
create table permnolist as
select distinct permno
from pricescorrel;
quit;
data permnolist;
set permnolist;
by permno;
permnoid + 1;
run;
%MACRO correlpairs();
proc sql noprint;
select distinct max(permnoid)
into :ttl_id
from permnolist;
quit;
%do ii=1 %to &ttl_id;
proc sql noprint;
select distinct permno
into :permnoa
from permnolist
where permnoid = ⅈ
quit;
%do jj=&ii %to &ttl_id;
proc sql noprint;
select distinct permno
into :permnob
from permnolist
where permnoid = &jj;
quit;
proc sql noprint;
create table company1 as
select date as olddate, *
from pricescorrel
where permno = &permnoa;
quit;
proc sql noprint;
create table company2 as
select date as olddate, *
from pricescorrel
where permno = &permnob;
quit;
proc sql noprint;
create table merged as
select coalesce(a.olddate, b.olddate) as date,
a.permno as permno1,
b.permno as permno2,
a.ret as ret1,
b.ret as ret2
from company1 as a
full join company2 as b
on a.olddate = b.olddate;
quit;
data merged;
set merged;
OBS = 1;
if nmiss(of ret1 -- ret2) > 1 then
delete;
else
if nmiss(of ret1 -- ret2) > 0 then
do;
ret1 = . ;
ret2 = . ;
OBS = . ;
end;
R12 = ret1 * ret2;
run;
proc expand DATA = merged OUT = mergedout METHOD = none;
convert ret1 = C1SUM / TRANSFORMOUT = (movsum 252);
convert ret2 = C2SUM / TRANSFORMOUT = (movsum 252);
convert R12 = C12SUM / TRANSFORMOUT = (movsum 252);
convert OBS = N / TRANSFORMOUT = (movsum 252);
convert ret1 = C1CSS / TRANSFORMOUT = (movcss 252);
convert ret2 = C2CSS / TRANSFORMOUT = (movcss 252);
run;
data mergedout(keep=date obs N permno1 permno2 ret1 ret2 rho);
set mergedout;
if missing(rho) then
delete;
rho = (C12SUM - (C1SUM * C2SUM)/N) / (sqrt(C1CSS) * sqrt(C2CSS));
rho = lag(rho);
run;
proc datasets nolist;
append base=mydat
data=mergedout;
quit;
proc datasets library = work nolist;
delete mergedout;
run;
%end;
%end;
proc export
data=mydat
outfile="mergedout.csv"
dbms=csv replace;
run;
%mend;
%correlpairs();