标题: 同志们,来帮额看这个问题怎么解决 [打印本页] 作者: shiyiming 时间: 2009-7-24 21:59 标题: 同志们,来帮额看这个问题怎么解决 先上样例
data a;
input id $ dt yymmdd10. stk $ type ;
format dt yymmdd10.;
cards;
10001 2001-12-12 100037 4
10001 2001-12-12 111001 1
10001 2001-12-21 100795 1
10001 2002-1-9 000973 1
10001 2002-1-9 100018 1
10001 2002-1-9 100392 1
10001 2002-1-9 100961 1
10001 2002-1-17 000973 4
10001 2002-1-17 111333 1
10001 2002-1-19 100795 4
10001 2002-1-19 100961 4
10001 2002-2-13 000931 4
10001 2002-2-13 111628 1
10001 2002-2-14 111001 4
10001 2002-3-23 100018 4
10001 2002-3-23 111333 4
10001 2002-4-19 100392 4
10001 2002-6-21 111628 4
10001 2002-6-21 111988 1
10001 2002-6-29 100018 1
10001 2002-8-13 111988 4
10001 2002-8-21 100018 4
10001 2002-10-25 100886 1
10001 2002-11-22 111857 1
10001 2003-4-23 111857 4
10001 2003-6-2 100037 1
10001 2003-6-2 111628 1
10001 2003-6-6 111988 1
10001 2003-6-12 100030 1
;
run;
说明:dt为交易日期,stk为股票代码,type 1=建仓 4=清仓。
目标:计算出id=10001在2001-12-01-2003-07-31期间空仓的时间长度,关键是怎么判断空仓开始结束以及程序实现?
不知道是否描述清楚? <!-- s:shock: --><img src="{SMILIES_PATH}/icon_eek.gif" alt=":shock:" title="Shocked" /><!-- s:shock: -->作者: shiyiming 时间: 2009-7-25 02:04 标题: Re: 同志们,来帮额看这个问题怎么解决 If one stk only has type 4 record, then 空仓的
时间长度=date of today minus the date you dumpped the stk.
Otherwise 空仓的时间长度=the date you bought the stk minus
the date you dumpped the stk last time.
for each stk the sum of day is the total days of 空仓的
时间长度.
data b(drop=dump_date);
set a;
by id stk dt;
retain day 0;
retain dump_date .;
if first.stk then day=0;
if (first.stk=1 and last.stk=1) then
do;
if type=1 then day=0;
if type=4 then day=today()-dt;
end;
if not (first.stk=1 and last.stk=1) then
do;
if type=4 then do; day=0; dump_date=dt; end;
if type=1 and not first.stk then do; day=day+dt-dump_date; dump_date=.; end;
if type=4 and last.stk then day=today()-dt;
end;
run;作者: shiyiming 时间: 2009-7-25 20:40 标题: Re: 同志们,来帮额看这个问题怎么解决 <!-- s:shock: --><img src="{SMILIES_PATH}/icon_eek.gif" alt=":shock:" title="Shocked" /><!-- s:shock: --> 看来是我未描述清楚,最终结果是按id来的,不需要分stk来(这样是很简单)......我自己再弄弄吧....作者: shiyiming 时间: 2009-7-25 23:27 标题: Re: 同志们,来帮额看这个问题怎么解决 7/8楼的钢鞭是哪一根?作者: shiyiming 时间: 2009-7-26 11:41 标题: Re: 同志们,来帮额看这个问题怎么解决 [code:11pos67z]data empty(keep=id status date ) stockstatus(keep=id dt stk stks empty);
set a;
by id dt;
format stks $32767. date yymmdd10. ;
retain stks '' lastempty lastdate ;
if _n_=1 then lastdate=dt;
if type=1 then stks=compbl(trim(stks)||' '||stk) ;
if type=4 then stks=tranwrd(stks,stk,'');
empty=(stks='');
if last.dt then
do;
output stockstatus;
do date=lastdate+1 to dt-1;status=lastempty; if '12feb2001'd<=date<='31jul2003'd and status=1 then output empty;end;
lastempty=empty;
lastdate=dt;
end;
run;[/code:11pos67z]
Empty 这个数据集的条数就是空仓的天数(未包括首尾的操作当天,可自己修改),怎么放入变量或者宏变量不要我教了吧?而且你可以从这个数据集中得到具体空仓的每一天。stockstatus数据集中可以看到每特定日期的持仓情况。可以作为验证。不过有一个感想。做股票的是不是应该请出主意的大家吃吃饭?作者: shiyiming 时间: 2009-7-26 16:20 标题: Re: 同志们,来帮额看这个问题怎么解决 首先感谢出主意的朋友们,请吃饭的话没问题,虽然俺不是做股票的,呵呵,不过不要太贵的地方就可以 <!-- s8) --><img src="{SMILIES_PATH}/icon_cool.gif" alt="8)" title="Cool" /><!-- s8) -->
我的跟ahuige的想法差不多,建持有股票集再操作..不过ahuige的程序有个小问题,假设有如下例:
[code:13lwj24a]data a;
input id $ dt yymmdd10. stk $ type ;
format dt yymmdd10.;
cards;
10001 2001-12-12 00037 1
10001 2001-12-21 00037 4
10001 2002-1-9 00973 4
10001 2002-1-9 00001 1
;
run;
data empty(keep=id status date ) stockstatus(keep=id dt stk stks empty);
set a;
by id dt;
format stks $32767. date yymmdd10. ;
retain stks '' lastempty lastdate ;
if _n_=1 then lastdate=dt;
if type=1 then stks=compbl(trim(stks)||' '||stk) ;
if type=4 then stks=tranwrd(stks,stk,'');
empty=(stks='');
if last.dt then
do;
output stockstatus;
do date=lastdate+1 to dt-1;status=lastempty; if '12feb2001'd<=date<='31jul2003'd and status=1 then output empty;end;
lastempty=empty;
lastdate=dt;
end;
run;[/code:13lwj24a]
实际该10001在2001-12-12->2002-1-9期间一直持有00973,而ahuige的结果2001-12-21->2002-1-9期间做空了 呵呵
/* 按起止时间补齐缺少的记录 */
data temp1;
set temp1;
by stk dt type;
output;
/* 补开始记录 */
if first.stk and type=4 then do;
dt=input("&start",yymmdd10.);
type=1;
output;
return;
end;
/* 补结束记录 */
if last.stk and type=1 then do;
dt=input("&end",yymmdd10.);
type=4;
output;
end;
run;
/* 建新的分组变量 */
/* temp2:转换为持仓区间的交易记录 */
data temp2;
set temp1;
if type=1 then flag=_n_;
else flag=_n_-1;
run;
/* 创建持仓期间 */
data temp2;
do _n_=1 by 1 until(last.flag);
set temp2;
by flag;
if type=1 then start=dt;
else end=dt;
end;
format start end yymmdd10.;
keep id stk start end;
run;
/* 按建仓时间排序 */
proc sort data=temp2;
by id start;
run;
/* 比较持仓区间 */
/* temp3:包含有效的持仓区间 */
data temp3;
set temp2;
retain start_dt end_dt;
if _n_=1 then do;
start_dt=start;
end_dt=end;
end;
else do;
if start>end_dt then start_dt=start;
if end>end_dt then end_dt=end;
end;
have_day=end_dt-start_dt;
output;
format start_dt end_dt yymmdd10.;
keep id start_dt end_dt have_day;
run;
/* 汇总持仓区间 */
data temp3;
do _n_=1 by 1 until(last.start_dt);
set temp3;
by start_dt;
end;
run;
/* result:结果数据 */
data result;
set temp3 end=last;
date_range=input("&end",yymmdd10.)-input("&start",yymmdd10.);
sum_have_day+have_day;
final_enpty_day=date_range-sum_have_day;
if last then output;
drop start_dt end_dt have_day;
run;[/code:fn5jnbfk]