用RHive从历史数据中提取逆回购信息

问题

RHive如何进行金融数据分析?

引言

笔者接触金融时间并不太长,操作的第一个产品就是逆回购。逆回购对于大部分人来说,都是一个新鲜词,就算是炒股多年的玩家,可能也是在2013年6月份发生银行缺钱的事件之后才了解逆回购的。隔夜的银行间拆借利率达到了30%,简单来说银行缺钱了!各种机构分分出售股票、债券,兑换成现金借给应银行。个人用户也都取出存款,通过逆回购,把钱借给银行。30%的利率,让所有人在那一周都为之兴奋,只有银行在惶恐。

6.6.1 逆回购简介

我们首先解释一下债券回购的含义,简单地说,债券质押式回购就是交易双方以债券为质押品的一种短期资金借贷行为。其中债券持有人(正回购方)将债券质押而获得资金使用权,到约定的时间还本并支付一定的利息,从而“赎回”债券。而资金持有人(逆回购方)就是正回购方的交易对手。在实际交易中债券是质押给了第三方,即中国结算公司,这样交易双方否更加安全,交易更便捷。

可回购的债券包括所有的国债、绝大部分企业债、公司债和分离债的纯债,它们都都可用于债券回购交易。沪深交易所每周都会公布可回购债券的折算率,上面没有但可交易的品种就是不可回购的债券。折算率就是把债券质押时,交易所按债券面值给出的可质押的比率。

现在交易的回购品种很多,不过我们下面仅列出个人投资者经常参与的公司债(包括企业债等)回购品种。上海证券交易所可交易的质押式回购(括号中为交易代码) 分为1日(204001)、2日(204002)、3日(204003)、4日(204004)、7日(204007)、14日(204014)、28日(204028)、91日(204091)、182日(204182)共9个品种。深圳交易所按回购期限分为分为1日(131810)、2日(131811)、3日(131800)、7日(131801)共4个品种。其中经常交易的只有沪深1日和7日四个品种,并且沪市的日均交易量又远远大于深市的交易量。

6.6.2 历史数据存储结构

本节使用的系统环境:

  • Linux: Ubuntu 12.04.2 LTS 64bit
  • R: 3.0.1 x86_64-pc-linux-gnu
  • 内网域名: c1.wtmart.com

Hive中的表结构:

> rhive.desc.table('t_reverse_repurchase')
    col_name data_type
1  tradedate    string
2  tradetime    string
3 securityid    string
4     bidpx1    double
5   bidsize1    double
6   offerpx1    double
7 offersize1    double

字段解释:

  • tradedate:交易日期
  • tradetime:交易时间
  • securityid:股票ID
  • bidpx1:买一
  • bidsize1:买一交易量
  • offerpx1:卖一
  • bidsize1:卖一交易量

6.6.3 通过用RHive提取数据

登陆c1.wtmart.com服务器,打开R的客户端。

~ R   # 启动R程序
> library(RHive)  # 加载RHive
> rhive.init()  #初始化
> rhive.connect("c1.wtmart.com")  #连接到Hive集群
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/cos/toolkit/hive-0.9.0/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/cos/toolkit/hadoop-1.0.3/lib/slf4j-log4j12-1.4.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

> rhive.list.tables()  #查看当前的表
              tab_name
1            t_hft_day   //历史数据表
2            t_hft_tmp   //临时表
4 t_reverse_repurchase   //逆回购表

查看所有股票历史数据分片:测试数据从20130627–20130726。

> rhive.query("SHOW PARTITIONS t_hft_day");  # 查看t_hft_day表的分片
            partition
1  tradedate=20130627
2  tradedate=20130628
3  tradedate=20130701
4  tradedate=20130702
5  tradedate=20130703
6  tradedate=20130704
7  tradedate=20130705
8  tradedate=20130708
9  tradedate=20130709
10 tradedate=20130710
11 tradedate=20130712
12 tradedate=20130715
13 tradedate=20130716
14 tradedate=20130719
15 tradedate=20130722
16 tradedate=20130723
17 tradedate=20130724
18 tradedate=20130725
19 tradedate=20130726

分为提取“上交所一天逆回购”(204001)和“深交所一天逆回购”(131810),从7月22日至7月26日的一周数据。

> rhive.drop.table("t_reverse_repurchase")  # 删除逆回购表

# 创建逆回购表,并插入数据
> rhive.query("CREATE TABLE t_reverse_repurchase AS SELECT tradedate,tradetime,securityid,bidpx1,bidsize1,offerpx1,offersize1 FROM t_hft_day where tradedate>=20130722 and securityid in (131810,204001)");

# 查看数据结果集
> rhive.query("SELECT securityid,count(1) FROM t_reverse_repurchase group by securityid");
  securityid  X_c1
1     131810 17061
2     204001 12441

加载到R的内存中。

# 从Hive查询数据,并赋值给R的变量bidpx1
> bidpx1<-rhive.query("SELECT securityid,concat(tradedate,tradetime) as tradetime,bidpx1 FROM t_reverse_repurchase"); #查看记录条数 > nrow(bidpx1)
[1] 29502

> head(bidpx1)  #查看数据
  securityid      tradetime bidpx1
1     131810 20130724145004  2.620
2     131810 20130724145101  2.860
3     131810 20130724145128  2.850
4     131810 20130724145143  2.603
5     131810 20130724144831  2.890
6     131810 20130724145222  2.600

用ggplot2做数据可视化,画出数据两个产品的一周的走势,所图6-1所示。

> library(ggplot2)  # 加载ggplot2
> g<-ggplot(data=bidpx1, aes(x=as.POSIXct(tradetime,format="%Y%m%d%H%M%S"), y=bidpx1))
> g<-g+geom_line(aes(group=securityid,colour=securityid))
> g<-g+xlab('tradetime')+ylab('bidpx1')
> ggsave(g,file="01.png",width=12,height=8) # 图片输出到文件

一周走势

图6-1 一周走势

对于一周的走势我们看不太清楚,再画出数据两个产品在2013年07月26日一天的走势,所图6-2所示。

> bidpx1<-rhive.query("SELECT securityid,concat(tradedate,tradetime) as tradetime,bidpx1 FROM t_reverse_repurchase WHERE tradedate=20130726");
> g<-ggplot(data=bidpx1, aes(x=as.POSIXct(tradetime,format="%Y%m%d%H%M%S"), y=bidpx1))
> g<-g+geom_line(aes(group=securityid,colour=securityid))
> g<-g+xlab('tradetime')+ylab('bidpx1')
> ggsave(g,file="02.png",width=12,height=8)

一天走势

6.6.4 策略模型及实现

打印出两幅图片的两条曲线,我们可以看到131810一直在追随204001的变化,并且大部情况都低于204001。 下面做一个简单的相关性的策略分析:通过204001变化,判断131810的卖点。

  1. 把131810和204001按每分钟标准化
  2. 设置当131810和204001有交点的时候,提取卖出信号
  3. 当131810和204001的后一个交点的卖一价格大于前一个交点的卖一价格10%以上,则把后一交点作为局部最优的卖出信号点。

提取131810和204001的数据,存储在t_reverse_repurchase表中

#登陆R
> library(RHive)
> rhive.init()
> rhive.connect("c1.wtmart.com")

#提取131810和204001的数据
> rhive.drop.table("t_reverse_repurchase")
> rhive.query("CREATE TABLE t_reverse_repurchase AS SELECT tradedate,tradetime,securityid,bidpx1,bidsize1,offerpx1,offersize1 FROM t_hft_day where securityid in (131810,204001)");

#查看数据集
> rhive.query("select count(1),tradedate from t_reverse_repurchase group by tradedate")
   X_c0 tradedate
1  4840  20130627
2  4792  20130628
3  4677  20130701
4  3124  20130702
5  2328  20130703
6  3787  20130704
7  4294  20130705
8  4977  20130708
9  4568  20130709
10 6619  20130710
11 5633  20130712
12 6159  20130715
13 5918  20130716
14 6200  20130719
15 6074  20130722
16 5991  20130723
17 5899  20130724
18 5346  20130725
19 6192  20130726
获得一天的数据并做ETL。
# 加载软件包
library(ggplot2)
library(scales)
library(plyr)

#把一周的数据加载到内存
bidpx1<-rhive.query(paste("SELECT securityid,tradedate,tradetime,bidpx1 FROM t_reverse_repurchase WHERE tradedate>=20130722"));

#加载一天的数据并做ETL
oneDay<-function(date){
  d1<-bidpx1[which(bidpx1$tradedate==date),]
  d1$tradetime2<-round( as.numeric(as.character(d1$tradetime))/100)*100

d1$tradetime2[which(d1$tradetime2<100000)]<-paste(0,d1$tradetime2[which(d1$tradetime2<100000)],sep="")

 d1$tradetime2[which(d1$tradetime2=='1e+05')]='100000'
  d1$tradetime2[which(d1$tradetime2=='096000')]='100000'
  d1$tradetime2[which(d1$tradetime2=='106000')]='110000'
  d1$tradetime2[which(d1$tradetime2=='126000')]='130000'
  d1$tradetime2[which(d1$tradetime2=='136000')]='140000'
  d1$tradetime2[which(d1$tradetime2=='146000')]='150000'
  d1
}

# 通过均值标准化
meanScale<-function(d1){
  ddply(d1, .(securityid,tradetime2), summarize, bidpx1=mean(bidpx1))
}

# 找到要分析的点
findPoint<-function(a1,a2){
  #找到所有a1大于a2的点
  bigger_point<-function(a1,a2){
    idx<-c()
    for(i in intersect(a1$tradetime2,a2$tradetime2)){
      i1<-which(a1$tradetime2==i)
      i2<-which(a2$tradetime2==i)
      if(a1$bidpx1[i1]-a2$bidpx1[i2]>=-0.02){
        idx<-c(idx,i1)
      }
    }
    idx
  }

  # 去掉连续的索引值
  remove_continuous_point<-function(idx){
    idx[-which(idx-c(NA,rev(rev(idx)[-1]))==1)]
  }

  idx<-bigger_point(a1,a2)
  remove_continuous_point(idx)
}

# 发现局部最优卖出点
findOptimize<-function(d3){
  idx2<-which((d3$bidpx1-c(NA,rev(rev(d3$bidpx1)[-1])))/d3$bidpx1>0.1)
  if(length(idx2)<1)
    print("No Optimize point")
  d3[idx2,]
}

# 画图查看结果
draw<-function(d2,d3,d4,date,png=FALSE){
  g<-ggplot(data=d2, aes(x=strptime(paste(date,tradetime2,sep=""),format="%Y%m%d%H%M%S"), y=bidpx1))
  g<-g+geom_line(aes(group=securityid,colour=securityid))
  g<-g+geom_point(data=d3,aes(size=1.5,colour=securityid))   if(nrow(d4)>0){
    g<-g+geom_text(data=d4,aes(label= format(d4$bidpx1,digits=4)),colour="blue",hjust=0, vjust=0)
  }
  g<-g+xlab('tradetime')+ylab('bidpx1')
  if(png){
    ggsave(g,file=paste(date,".png",sep=""),width=12,height=8)
  }else{
    g
  }
}

# 执行策略封装
date<-20130722
d1<-oneDay(date)
d2<-meanScale(d1)
a1<-d2[which(d2$securityid==131810),]
a2<-d2[which(d2$securityid==204001),]
d3<-d2[findPoint(a1,a2),]
d4<-findOptimize(d3)
draw(d2,d3,d4,as.character(date),TRUE)

下面分别生成一周数据的5张图,20130722对应图6-3、20130723对应图6-4、20130724对应图6-5、20130725对应图6-6和20130726对应图6-7 。对这一周数据的回测,在图中显示了程序化策略给出的信号点,都是比较理想的卖出时机,比我自己在当天操作时卖出的利率要高不少。

 2013年07月22日策略可视化

图6-3 2013年07月22日策略可视化

2013年07月23日策略可视化 图6-4 2013年07月23日策略可视化

2013年07月24日策略可视化

图6-5 2013年07月24日策略可视化

2013年07月25日策略可视化

图6-6 2013年07月25日策略可视化

2013年07月26日策略可视化

通过对一周数据的比较我们发现,这个简单的策略能给我们带来一些收益。虽然不是全局最优的,但比人为的判断会更有依据。

results matching ""

    No results matching ""