现在的位置: 首页 > 综合 > 正文

动量策略&反转策略初探sas

2018年10月21日 ⁄ 综合 ⁄ 共 9659字 ⁄ 字号 评论关闭

MBAlib百科对动量策略和反转策略作了很好的解释:

动量/反向策略是指买入赢家/输家组合,同时卖空输家/赢家组合的交易策略。其主要步骤为:

  ①确定目标证券市场作为交易对象的范围。

  ②选定一个时间长度作为证券业绩评价期,通常称为投资组合的形成期或排名期。

  ③计算形成期各样本证券收益率

  ④根据形成期各样本证券的收益率的大小,对目标市场所有样本证券进行升序、降序排列,然后等分成若干组,其中收益率最大的一组称为赢家组合,收益率最小的一组称为输家组合。

  ⑤形成期之后或间隔一段时间后,再选一个时间长度,作为卖买赢家组合和输家组合后的持有期限。

  ⑥连续或间隔一段时期,不断重复 ②一⑤行为。

  ⑦业绩评价。计算动量/反向策略各持有期的回报率均值及t统计值,如果t统计值表明动量/反转策略的收益率显著大少0,实业界则称动量/反向策略成功,学术界称存在动量/反转现象,反之亦反。

本人尝试着用sas一步一步完成上述操作:股票范围为国内整个A股,形成期用P周来表示,组合持有期用Q周表示,这里将P,Q都简单的取1,2,3。后续的T检验待继续完善。

这里test数据系包含2000多只A股的日线数据。

* test系多只股票的日线数据,选取2009-2012年度日线数据;
data test1;
   set test;
       year=year(date);
       month=month(date);
       week=week(date);
   keep id date year month week close ; 
   if    2009<=year<=2012 then output;
run;
*计算两年期间股票的日线数据长度,剔除较短数据;
proc freq data=test1 noprint ;
   table id /out=test2(keep=id count)   ;
run;
data test3;
   merge test1 test2;
   by id;
   if count<360  then delete ;
   if id eq lag(id)	then do;
   ret_1=log(close)-log(lag(close));
   end;
run;

proc sort data=test3;by id;run;
*计算每支股票的周累计收益;
proc sql;
   create table test4 as
      select *,
	         sum(ret_1) as sum_ret
		 from test3	
		 group by id,year,month,week;
quit;
*计算日均收益率,对其进行排序,进而对2000多只股票进行分组;
proc sql;
   create table test5 as
      select distinct id,year,month,week,sum_ret
	     from test4;
quit;


*选定一个测试时点,例如以2011年1月第一周开始,找到该时点前p周到数据,
进而按照前P周到累计收益率进行排序,这里p取1,2,3;
data test6;
   set test5;
   if id eq lag(id) then do;
      ret_lag1=lag(sum_ret);
      ret_lag2=lag(sum_ret)+lag2(sum_ret);
      ret_lag3=ret_lag2+lag3(sum_ret);
   end;
run;
*考虑lag函数产生缺失值的问题,我们选取观测时间点位2011年1月第一周;
data test7;
   set test6;
   if year=2011 & month=1 & week=1 then output;
run;

*对观测时间点进行前P周到累计收益进行排序:升序:轮转策略;降序:动量策略;
%macro rank(num);
%do i=1 %to &num;
proc rank data=test7 out=test7_&i group=14;
   var ret_lag&i;
   ranks group;
run;
data test_dong&i test_fan&i;
   set test7_&i;
   if group=0 then output test_fan&i;
   if group=13 then output test_dong&i;
run;

*从待选股票中选出动量组合股票,从观测日开始,计算持有组合内股票Q周的累计收益;

data new;
   set test6;
   if year<2011 then delete;
run;
*计算动量策略形成期为1周,持有期为1,2,3周到收益,同理可以计算
形成期为2/3周到动量策略;


data merge_d&i;
   merge test_dong&i(in=a) new(in=b);
   by id;
   if  a=1 & b=1 then output;
run;
proc expand data=merge_d&i out=d_&i;
   convert ret_lag1=ret1 / transform=(lead 2);
   convert ret_lag2=ret2 / transform=(lead 3);
   convert ret_lag3=ret3 / transform=(lead 4);
run;
data d_&i;
   set d_&i;
   if year=2011 & month=1 & week=1 then output;
run;

%end;
%mend;
%rank(3);

试图将上面代码得到的组合和沪深300指数进行比对,考察其收益率情况。下面需要计算相应时间段的沪深300指数收益率,进而进行差值比对。沪深300指数数据需要首先下载。

*沪深300指数收益率的计算;
data sz399300_1;
   set sz399300;
   year=year(var1);
   month=month(var1);
   week=week(var1);
   ret=dif(log(var5));
   drop var: ;
run;
   
proc sql;
   create table sz399300_2 as
      select distinct year,month,week,
	                  sum(ret) as sum_ret
	     from sz399300_1
		 group by year,month,week ;
quit;

data sz399300_3;
   set sz399300_2;
   ret_lag1=lag(sum_ret);
   ret_lag2=lag(sum_ret)+lag2(sum_ret);
   ret_lag3=ret_lag2+lag3(sum_ret);
run;

proc expand data=sz399300_3 out=sz399300_4;
   convert ret_lag1=ret1 / transform=(lead 2);
   convert ret_lag2=ret2 / transform=(lead 3);
   convert ret_lag3=ret3 / transform=(lead 4);
run;
data sz399300_4;
   set sz399300_4;
   if year=2011 & month=1 & week=1 then output;
run;


*沪深300与组合收益率比较;
%macro diff_hs(num);
%do i= 1 %to &num;
proc sql;
   create table d&i_need as
      select distinct a.year,a.month,a.week,
	         mean(a.ret1-b.ret1) as ret1,
			 mean(a.ret2-b.ret2) as ret2,
			 mean(a.ret3-b.ret3) as ret3
	  from d_&i as a
	  join sz399300_4 as b
	  on a.year=b.year;
quit;

proc sql;
   create table f&i_need as
      select distinct a.year,a.month,a.week,
	         mean(a.ret1-b.ret1) as ret1,
			 mean(a.ret2-b.ret2) as ret2,
			 mean(a.ret3-b.ret3) as ret3
	  from f_&i as a
	  join sz399300_4 as b
	  on a.year=b.year;
quit;

%end;
%mend;

%diff_hs(3);

 

下面系组合形成期和持有期(p,q)都用月来表示的代码:

libname yu "E:\TMP";
* test系多只股票的日线数据,选取2009-2012年度日线数据;
data test1;
   set YU.test;
       year=year(date);
       month=month(date);
   keep id date year month  close ; 
   if    2009<=year<=2012 then output;
run;
*计算两年期间股票的日线数据长度,剔除较短数据;
proc freq data=test1 noprint ;
   table id /out=test2(keep=id count)   ;
run;
data test3;
   merge test1 test2;
   by id;
   if count<360  then delete ;
   if id eq lag(id)	then do;
   ret_1=log(close)-log(lag(close));
   end;
run;

proc sort data=test3;by id;run;
*计算每支股票的月累计收益;
proc sql;
   create table test4 as
      select distinct id,year,month,
	         sum(ret_1) as sum_ret
		 from test3	
		 group by id,year,month;
quit;

*选定一个测试时点,例如以2011年1月1日开始,找到该时点前p月到数据,
进而按照前P月到累计收益率进行排序,这里p取1,2,3,4,5,6;
data test5;
   set test4;
   if id eq lag(id) then do;
      ret_lag1=lag(sum_ret);
      ret_lag2=lag(sum_ret)+lag2(sum_ret);
      ret_lag3=ret_lag2+lag3(sum_ret);
	  ret_lag4=ret_lag3+lag4(sum_ret);
	  ret_lag5=ret_lag4+lag5(sum_ret);
	  ret_lag6=ret_lag5+lag6(sum_ret);
   end;
run;

*考虑lag函数产生缺失值的问题,我们选取观测时间点位2011年1月第一周;
data test6;
   set test5;
   if year=2011 & month=10  then output;
run;

*对观测时间点进行前P周到累计收益进行排序:升序:轮转策略;降序:动量策略;
%macro rank(num);
%do i=1 %to &num;
proc rank data=test6 out=test6_&i group=14;
   var ret_lag&i;
   ranks group;
run;
data test_dong&i test_fan&i;
   set test6_&i;
   if group=0 then output test_fan&i;
   if group=13 then output test_dong&i;
run;

*从待选股票中选出动量组合股票,从观测日开始,计算持有组合内股票Q周的累计收益;

data new;
   set test6;
   if year<2011 then delete;
run;
*计算动量策略形成期为1周,持有期为1,2,3周到收益,同理可以计算
形成期为2/3周到动量策略;


data merge_d&i;
   merge test_dong&i(in=a) new(in=b);
   by id;
   if  a=1 & b=1 then output;
run;
proc expand data=merge_d&i out=d_&i;
   convert ret_lag1=ret1 / transform=(lead 2);
   convert ret_lag2=ret2 / transform=(lead 3);
   convert ret_lag3=ret3 / transform=(lead 4);
   convert ret_lag4=ret4 / transform=(lead 5);
   convert ret_lag5=ret5 / transform=(lead 6);
   convert ret_lag6=ret6 / transform=(lead 7);
run;
data d_&i;
   set d_&i;
   if year=2011 & month=10  then output;
run;

data merge_f&i;
   merge test_fan&i(in=a) new(in=b);
   by id;
   if  a=1 & b=1 then output;
run;
proc expand data=merge_f&i out=f_&i;
   convert ret_lag1=ret1 / transform=(lead 2);
   convert ret_lag2=ret2 / transform=(lead 3);
   convert ret_lag3=ret3 / transform=(lead 4);
   convert ret_lag4=ret4 / transform=(lead 5);
   convert ret_lag5=ret5 / transform=(lead 6);
   convert ret_lag6=ret6 / transform=(lead 7);
run;
data f_&i;
   set f_&i;
   if year=2011 & month=10  then output;
run;
%end;
%mend;
%rank(6);

*沪深300指数收益率的计算;
data sz399300_1;
   set YU.sz399300;
   year=year(var1);
   month=month(var1);
   ret=dif(log(var5));
   drop var: ;
run;
   
proc sql;
   create table sz399300_2 as
      select distinct year,month,
	                  sum(ret) as sum_ret
	     from sz399300_1
		 group by year,month ;
quit;

data sz399300_3;
   set sz399300_2;
   ret_lag1=lag(sum_ret);
   ret_lag2=lag(sum_ret)+lag2(sum_ret);
   ret_lag3=ret_lag2+lag3(sum_ret);
   ret_lag4=ret_lag3+lag4(sum_ret);
   ret_lag5=ret_lag4+lag5(sum_ret);
   ret_lag6=ret_lag5+lag6(sum_ret);
run;

proc expand data=sz399300_3 out=sz399300_4;
   convert ret_lag1=ret1 / transform=(lead 2);
   convert ret_lag2=ret2 / transform=(lead 3);
   convert ret_lag3=ret3 / transform=(lead 4);
   convert ret_lag4=ret4 / transform=(lead 5);
   convert ret_lag5=ret5 / transform=(lead 6);
   convert ret_lag6=ret6 / transform=(lead 7);
run;
data sz399300_4;
   set sz399300_4;
   if year=2011 & month=10  then output;
run;


%macro diff_hs(num);
%do i= 1 %to &num;
proc sql;
   create table d_need&i as
      select distinct a.year,a.month,
	         mean(a.ret1-b.ret1) as ret1,
			 mean(a.ret2-b.ret2) as ret2,
			 mean(a.ret3-b.ret3) as ret3,
	         mean(a.ret4-b.ret4) as ret4,
			 mean(a.ret5-b.ret5) as ret5,
			 mean(a.ret6-b.ret6) as ret6
	  from d_&i as a
	  join sz399300_4 as b
	  on a.year=b.year;
quit;

proc sql;
   create table f_need&i as
      select distinct a.year,a.month,
	         mean(a.ret1-b.ret1) as ret1,
			 mean(a.ret2-b.ret2) as ret2,
			 mean(a.ret3-b.ret3) as ret3,
			 mean(a.ret4-b.ret4) as ret4,
			 mean(a.ret5-b.ret5) as ret5,
			 mean(a.ret6-b.ret6) as ret6
	  from f_&i as a
	  join sz399300_4 as b
	  on a.year=b.year;
quit;

%end;
%mend;

%diff_hs(6);


data final_d9; 
   set d_need:;
run;
data final_f9;
   set f_need:;
run;
proc datasets library=work;
   delete d_: f_: merge_: Sz399300: test: new;
run;
quit;

如果以日为单位进行测试,可以稍微变化下:

*e:\temp\test系国内A股数据,sz399300系沪深300指数数据;
libname gao "e:\tmp";
data test1;
   set gao.test;
   if id eq lag(id)	then do;
      ret=dif(close)/lag(close);
   end;
   if year(date)<2009 then delete; 
   keep id date ret close;
run;

*计算两年期间股票的日线数据长度,剔除较短数据;
proc freq data=test1 noprint ;
   table id /out=test2(keep=id count)   ;
run;
data test3;
   merge test1 test2;
   by id;
   if count<360  then delete ;
run;

*选定一个测试时点,例如以2011年1月5日,计算前P日累计收益率并进行排序,
这里p取21,42;
proc expand data=test3 out=test4 method=none;
   by id;
   convert ret =ret_lag1 / transformout=(movsum 21);
   convert ret =ret_lag2 / transformout=(movsum 42);   
run;
*选定测试日;
data test5;
   set test4;
   if date="05jan2012"d then output;
run;

*以05jan2011日前21/42日累计收益率进行排序,生产动量组合和反转组合;
%macro rank(num);
%do i=1 %to &num;
proc rank data=test5 out=test5_&i group=10;
   var ret_lag&i;
   ranks group;
run;
data test_dong&i test_fan&i;
   set test5_&i;
   if group=0 then output test_fan&i;
   if group=9 then output test_dong&i;
run;

*从待选股票中选出动量组合股票,从观测日开始,计算持有组合内股票Q日的累
计收益;

data new;
   set test4;
   if date<"05jan2012"d then delete;
run;
*计算动量策略形成期为1,持有期为1,2,3收益,同理可以计算
形成期为2/3到动量策略;

data merge_d&i;
   merge test_dong&i(in=a) new(in=b);
   by id;
   if  a=1 & b=1 then output;
run;
proc expand data=merge_d&i out=d_&i;
   convert ret_lag1=ret1 / transform=(lead 21);
   convert close=close21 / transform=(lead 21);
   convert ret_lag2=ret2 / transform=(lead 42);
   convert close=close42 / transform=(lead 42);

run;

data d_&i;
   set d_&i;
   if date="05jan2012"d  then output;
run;

data merge_f&i;
   merge test_fan&i(in=a) new(in=b);
   by id;
   if  a=1 & b=1 then output;
run;
proc expand data=merge_f&i out=f_&i;
   convert ret_lag1=ret1 / transform=(lead 21);
   convert close=close21 / transform=(lead 21);
   convert ret_lag2=ret2 / transform=(lead 42);
   convert close=close42 / transform=(lead 42);
run;
data f_&i;
   set f_&i;
   if date="05jan2012"d then output;
run;
%end;
%mend;
%rank(2);


*沪深300指数收益率的计算;

data sz399300_1;
   set gao.sz399300(rename=(var1=date var5=close));
   ret=dif(close)/lag(close);
   drop var: ;
run;

proc expand data=sz399300_1 out=sz399300_2 method=none;
   convert ret =ret_lag1 / transformout=(sum 21);
   convert ret =ret_lag2 / transformout=(sum 42); 
run;

proc expand data=sz399300_2 out=sz399300_3;
   convert ret_lag1=ret1 / transform=(lead 21);
   convert close=close21 / transform=(lead 21);
   convert ret_lag2=ret2 / transform=(lead 42);
   convert close=close42 / transform=(lead 42);
run;
data sz399300_4;
   set sz399300_3;
   c0=close*300;
   c21=close21*300;
   C42=close42*300;
   if date="05jan2012"d  then output;
run;


%macro diff_hs(num);
%do i= 1 %to &num;
proc sql;
   create table d_need&i as
      select distinct a.date,
	         mean(a.ret1-b.ret1) as ret1,
			 mean(a.ret2-b.ret2) as ret2,
            (sum((ceil(b.c0/193)/a.close)*a.close21) -c21)/c0 as r21,	
            (sum((ceil(b.c0/193)/a.close)*a.close42) -c42)/c0 as r42

	  from d_&i as a
	  join sz399300_4 as b
	  on a.date=b.date;
quit;

proc sql;
   create table f_need&i as
      select distinct a.date,
	         mean(a.ret1-b.ret1) as ret1,
			 mean(a.ret2-b.ret2) as ret2,
            (sum((ceil(b.c0/193)/a.close)*a.close21) -c21)/c0 as r21,	
            (sum((ceil(b.c0/193)/a.close)*a.close42) -c42)/c0 as r42
	  from f_&i as a
	  join sz399300_4 as b
	  on a.date=b.date;
quit;

%end;
%mend;

%diff_hs(2);



data final_d1; 
   set d_need:;
run;
data final_f1;
   set f_need:;
run;

 

抱歉!评论已关闭.