SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 1056|回复: 8
打印 上一主题 下一主题

同志们,来帮额看这个问题怎么解决

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2009-7-24 21:59:26 | 只看该作者

同志们,来帮额看这个问题怎么解决

先上样例
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: -->
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2009-7-25 02:04:12 | 只看该作者

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;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2009-7-25 20:40:41 | 只看该作者

Re: 同志们,来帮额看这个问题怎么解决

<!-- s:shock: --><img src="{SMILIES_PATH}/icon_eek.gif" alt=":shock:" title="Shocked" /><!-- s:shock: --> 看来是我未描述清楚,最终结果是按id来的,不需要分stk来(这样是很简单)......我自己再弄弄吧....
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2009-7-25 23:27:29 | 只看该作者

Re: 同志们,来帮额看这个问题怎么解决

7/8楼的钢鞭是哪一根?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2009-7-26 11:41:52 | 只看该作者

Re: 同志们,来帮额看这个问题怎么解决

[code:11pos67z]data empty(keep=id status date ) stockstatus(keep=id dt stk stks empty);
  set a;
  by id dt;
  format stks $32767&#46; date yymmdd10&#46; ;
  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&#46;dt then
  do;
    output stockstatus;
    do date=lastdate+1 to dt-1;status=lastempty; if '12feb2001'd&lt;=date&lt;='31jul2003'd and status=1 then output empty;end;
    lastempty=empty;
    lastdate=dt;
  end;
run;[/code:11pos67z]
Empty 这个数据集的条数就是空仓的天数(未包括首尾的操作当天,可自己修改),怎么放入变量或者宏变量不要我教了吧?而且你可以从这个数据集中得到具体空仓的每一天。stockstatus数据集中可以看到每特定日期的持仓情况。可以作为验证。不过有一个感想。做股票的是不是应该请出主意的大家吃吃饭?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2009-7-26 16:20:07 | 只看该作者

Re: 同志们,来帮额看这个问题怎么解决

首先感谢出主意的朋友们,请吃饭的话没问题,虽然俺不是做股票的,呵呵,不过不要太贵的地方就可以 <!-- s8) --><img src="{SMILIES_PATH}/icon_cool.gif" alt="8)" title="Cool" /><!-- s8) -->
我的跟ahuige的想法差不多,建持有股票集再操作..不过ahuige的程序有个小问题,假设有如下例:
[code:13lwj24a]data a;
input id $ dt yymmdd10&#46; stk $ type ;
format dt yymmdd10&#46;;
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&#46; date yymmdd10&#46; ;
  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&#46;dt then
  do;
    output stockstatus;
    do date=lastdate+1 to dt-1;status=lastempty; if '12feb2001'd&lt;=date&lt;='31jul2003'd and status=1 then output empty;end;
    lastempty=empty;
    lastdate=dt;
  end;
run;[/code:13lwj24a]
实际该10001在2001-12-12-&gt;2002-1-9期间一直持有00973,而ahuige的结果2001-12-21-&gt;2002-1-9期间做空了 呵呵

另外也很感谢&quot;死猪头&quot;,还没仔细看你的代码.....  <!-- s:? --><img src="{SMILIES_PATH}/icon_confused.gif" alt=":?" title="Confused" /><!-- s:? -->

看代码真的是比写难多了 呵呵 我瞎JB说的.......
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
7#
 楼主| 发表于 2009-7-26 19:28:48 | 只看该作者

Re: 同志们,来帮额看这个问题怎么解决

问题算不算问题看来是个问题。原来你们分析客户数据原来是可以从中间开始。。。。。不要求有客户先持仓,直接就可以先清仓。。。。。。。。。。有意思。那我请问,如果是这样的情况也可以,那一个客户手里永远有一只股票,是以前买的。你们没有以前他建仓的数据,但他就是不卖,所以你们也没有清仓的数据。那其实这个人永远都不是空仓的。但谁写的程序能正确判断出这个人是没有空窗期的?掐指一算?你们公司的业务不能这样吧?理论上任意一个客户手里都有可能有以前买的但现在还没卖的股票,所以所有人都有可能无空窗期,逻辑大大的有漏洞。。。。。我手持钢鞭将你打啊,将你打。。。。。。。。。。。。。。。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
8#
 楼主| 发表于 2009-7-26 20:43:11 | 只看该作者

Re: 同志们,来帮额看这个问题怎么解决

钢鞭抽的好疼........幸好准备了件防鞭衣
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
9#
 楼主| 发表于 2009-7-27 10:43:27 | 只看该作者

Re: 同志们,来帮额看这个问题怎么解决

凑个热闹,瞎写的.
[code:fn5jnbfk]data original;
        input id&#58; $ dt&#58; yymmdd10&#46; stk&#58; $ type ;
        format dt yymmdd10&#46;;
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
;

/* 设定起止时间 */
%let start=2001-12-01;
%let end=2003-07-31;

/* 对原始数据排序 */
/* temp1&#58;补齐记录的交易数据 */
proc sort data=original out=temp1;
        by stk dt type;
run;

/* 按起止时间补齐缺少的记录 */
data temp1;
        set temp1;
        by stk dt type;
        output;
        /* 补开始记录 */
        if first&#46;stk and type=4 then do;
                dt=input(&quot;&amp;start&quot;,yymmdd10&#46;);
                type=1;
                output;
                return;
        end;
        /* 补结束记录 */
        if last&#46;stk and type=1 then do;
                dt=input(&quot;&amp;end&quot;,yymmdd10&#46;);
                type=4;
                output;
        end;
run;

/* 对temp1重新排序 */
proc sort data=temp1;
        by stk dt type;
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&#46;flag);
                set temp2;
                by flag;
                if type=1 then start=dt;
                else end=dt;
        end;
        format start end yymmdd10&#46;;
        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&gt;end_dt then start_dt=start;
                                if end&gt;end_dt then end_dt=end;
                        end;
                have_day=end_dt-start_dt;
        output;
        format start_dt end_dt yymmdd10&#46;;
        keep id start_dt end_dt have_day;
run;

/* 汇总持仓区间 */
data temp3;
        do _n_=1 by 1 until(last&#46;start_dt);
                set temp3;
                by start_dt;
        end;
run;

/* result:结果数据 */
data result;
        set temp3 end=last;
        date_range=input(&quot;&amp;end&quot;,yymmdd10&#46;)-input(&quot;&amp;start&quot;,yymmdd10&#46;);
        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]
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|SAS中文论坛  

GMT+8, 2026-2-5 21:31 , Processed in 0.311990 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表