我的数据集&RAWDATA
类似于以下示例:
| Symbol | Date | Time | BB | BO | MIDPRICE |
|--------|----------|------|----|----|----------|
| AAPL | 20130102 | 2 | 2 | 3 | 2.5 |
| AAPL | 20130102 | 3 | 1 | 3 | 1.5 |
| ... | | | | | |
| AAPL | 20130102 | 100 | 3 | 4 | 3.5 |
| FB | 20130102 | 1 | 3 | 6 | 4.5 |
| FB | 20130102 | 3 | 3 | 5 | 4 |
| ... | | | | | |
| FB | 20130102 | 100 | 3 | 4 | 3.5 |
在特定时间每个符号只有一行。
现在,我想处理这个数据集,以便时间变量从1开始并且是连续的。如果在特定时间没有记录,则在此时创建新记录,将所有值设置为上一记录。
正确的输出应该是:
| Symbol | Date | Time | BB | BO | MIDPRICE |
|--------|----------|------|----|----|----------|
| AAPL | 20130102 | 1 | 2 | 3 | 2.5 |
| AAPL | 20130102 | 2 | 2 | 3 | 2.5 |
| AAPL | 20130102 | 3 | 1 | 3 | 1.5 |
| ... | | | | | |
| AAPL | 20130102 | 100 | 3 | 4 | 3.5 |
| FB | 20130102 | 1 | 3 | 6 | 4.5 |
| FB | 20130102 | 2 | 3 | 6 | 4.5 |
| FB | 20130102 | 3 | 3 | 5 | 4 |
| ... | | | | | |
| FB | 20130102 | 100 | 3 | 4 | 3.5 |
我已经尝试了以下代码,但它似乎不能正常运行:
/*
* Macro to fill in the gap seconds
*/
%MACRO GAP_SEC(RAWDATA);
data GAPDATA;
SET &RAWDATA; by symbol date;
retain SYMBOL DATE TIME BB BO MIDPRICE;
LAG_SYMBOL = lag(SYMBOL);
LAG_DATE = lag(DATE);
LAG_TIME = lag(TIME);
LAG_BB = lag(BB);
LAG_BO = lag(BO);
LAG_MIDPRICE = lag(MIDPRICE);
if first.symbol and first.date then
DO;
if TIME NE 1;
N = TIME - 1;
DO WHILE(N>1);
SYMBOL=SYMBOL;
BB=BB;
BO=BO;
MIDPRICE = MIDPRICE;
TIME=TIME-1;
output;
n=n-1;
END;
END;
else
do;
TIME_DIFF = TIME - LAG_TIME;
if TIME_DIFF > 1 then
DO;
M=TIME_DIFF;
DO WHILE(M>1);
SYMBOL = LAG_SYMBOL;
TIME = TIME + 1;
DATE = LAG_DATE;
BB = LAG_BB;
BO = LAG_BO;
MIDPRICE = LAG_MIDPRICE;
output;
M=M-1;
END;
END;
end;
drop LAG_SYMBOL LAG_DATE LAG_TIME LAG_BB LAG_BO LAG_MIDPRICE TIME_DIFF N M;
run;
/* Add new obs to original data set */
proc append base=&RAWDATA data=GAPDATA;
run;
proc sort data=&RAWDATA force; by Symbol Date Time; run;
%mend;
它不会填补空白,它也会生成具有相同时间和相同符号的重复记录。 (请注意,在原始数据集中,每个符号在特定时间只有一条记录)。例如,数据集可能变为:
| Symbol | Date | Time | BB | BO | MIDPRICE |
|--------|----------|------|----|----|----------|
| AAPL | 20130102 | 2 | 2 | 3 | 2.5 |
| AAPL | 20130102 | 2 | 2 | 3 | 2.5 |
| AAPL | 20130102 | 3 | 1 | 3 | 1.5 |
| ... | | | | | |
| AAPL | 20130102 | 100 | 3 | 4 | 3.5 |
| FB | 20130102 | 1 | 3 | 6 | 4.5 |
| FB | 20130102 | 1 | 3 | 6 | 4.5 |
| FB | 20130102 | 3 | 3 | 5 | 4 |
| ... | | | | | |
| FB | 20130102 | 100 | 3 | 4 | 3.5 |
我在这里做错了什么?
此外,我也希望所有符号同时结束。例如,最大时间可以是100 - 它不能无限增加。
更新:
如果时间1没有记录,我想先忽略它,并在后面的代码中做一些事情:
set &RAWDATA; by Symbol;
if not missing(Symbol);
/* retain the price from last second */
retain MIDPRICE CUM_RETURN;
LAG_MIDPRICE = lag(MIDPRICE);
LAG_CUMRETURN = lag(CUM_RETURN);
/* Make sure we are calculating the same ticker*/
return_sec = (MIDPRICE - LAG_MIDPRICE) / LAG_MIDPRICE;
if first.symbol then
do;
CUM_RETURN = 0;
return_sec = 0;
end;
CUM_RETURN = sum(CUM_RETURN, return_sec);
RMIN = 0.01/MIDPRICE;
drop LAG_MIDPRICE LAG_CUMRETURN BB BO MIDPRICE CUM_RETURN RMIN;
run;
如您所见,我稍后会计算符号的回报。因此,如果没有时间1,而不是将BB,BO或MIDPRICE设置为0,我想将时间1的return_sec设置为0,直到出现第一条记录。
答案 0 :(得分:2)
使用SAS / ETS中的PROC EXPAND
。这允许您扩展系列。 METHOD=STEP
选项将带有最后一个非缺失值。
我修改了FB的示例数据,以测试不以100结尾的变量。
data have;
infile datalines delimiter="|";
informat symbol $6.
date anydtdte.;
format date date9.;
input Symbol $ Date time bid offer mid;
datalines;
AAPL | 20130102 | 2 | 2 | 3 | 2.5
AAPL | 20130102 | 3 | 1 | 3 | 1.5
AAPL | 20130102 | 100 | 3 | 4 | 3.5
FB | 20130102 | 1 | 3 | 6 | 4.5
FB | 20130102 | 3 | 3 | 5 | 4
FB | 20130102 | 90 | 3 | 4 | 3.5
;
此数据步骤将最后一个值的值添加到100。
data have;
set have;
by symbol date;
if last.date then do;
if time ^= 100 then do;
do time=time to 100;
output;
end;
end;
else
output;
end;
else
output;
run;
PROC EXPAND
填补了空白。
proc expand data=have out=want to=day method=step;
by symbol date;
id time;
convert bid;
convert offer;
convert mid;
run;
PROC EXPAND
尝试提供帮助并将时间设置为日期。只需更改格式即可。
proc datasets lib=work nolist;
modify want;
format time best.;
run;
quit;