用R语言分析股票指数变化
杨旭东(2012-3-6)
今天商学院的一个同学写毕业论文时遇到点麻烦,于是找我帮忙。要求是这样的:已知一段时间内每日的股票开盘和收盘指数,以及若干股票的招股开始日期(发行日)和上市日期,要求这两个日期之间股票指数的变化情况。如下图所示,其中浅绿色的部分是我用R语言算出来的。
计算公式如下:指数变化=(上市首日收盘指数-发行日开盘指数)/ 发行日开盘指数。
首先,准备两份数据:
1. 每日的股票开盘和收盘指数,即上图中的第1、2、5列,保存在D盘下面,文件名为stock1.csv(用Excel另存为csv格式(逗号分隔的数据))。
2. 股票的上市日期和发现日期,即上图中的第6、8列,保存为“D:\stock.txt”(用制表符分隔数据项)。
接着在R语言控制台中设置好工作目录:
> setwd("D:\\") #注意这里转义字符‘\’的使用
> getwd()
[1] "D:/"
读入第一份数据:
Ø dict <-read.csv("stock1.csv")
Ø > dict
Ø 日期 开盘 收盘
Ø 1 2001-11-1 1692.35 1707.75
Ø 2 2001-11-2 1703.92 1691.35
Ø 3 2001-11-5 1687.84 1679.57
Ø 4 2001-11-6 1678.17 1671.27
Ø 5 2001-11-7 1669.42 1594.05
Ø 6 2001-11-8 1566.52 1605.87
Ø 7 2001-11-9 1605.07 1630.35
Ø 8 2001-11-12 1631.79 1621.19
Ø 9 2001-11-13 1609.95 1615.93
Ø 10 2001-11-14 1615.75 1617.10
Ø ……
共有2493条数据。
接着读入第二份数据:
Ø stock <-read.delim("stock.txt") #注意这里用了不同的数据读入函数
Ø > stock
Ø 上市日期招股开始日期
Ø 1 2001-11-29 2001-11-6
Ø 2 2001-12-6 2001-11-13
Ø 3 2001-12-12 2001-11-29
Ø 4 2001-12-18 2001-11-22
Ø 5 2001-12-20 2001-12-6
Ø 6 2001-12-25 2001-11-29
Ø 7 2001-12-26 2001-12-13
Ø 8 2001-12-27 2001-12-12
Ø 9 2002-1-8 2001-12-19
Ø 10 2002-1-11 2001-12-19
Ø 11 2002-1-16 2001-12-24
Ø 12 2002-1-31 2002-1-16
Ø 13 2002-2-5 2002-1-21
Ø 14 2002-2-7 2002-1-22
Ø ……
共有1234条数据。
注意两份数据的长度不一样,而且第一份数据中某些日期的数据缺失了,这给我后面的编程带来了一点小小的麻烦。
第一份数据存在对象dict里,第二份数据存在对象stock里,这两个对象都是数据帧(data frame)类型,即向量的数组。也就是说数据帧里的每个元素是一个向量,如上述两份文件的某一列,而且这些向量的类型可以不同。
开始主程序:
#首先创建一个数值型的向量,保存最后的计算结果
point <- numeric(length(stock$上市日期))
#主循环
for (i in 1:length(stock$上市日期))
{
x<- which(dict$日期 == stock$上市日期[i])
y<- which(dict$日期 == stock$招股开始日期[i])
point[i]<- (dict$收盘[x] - dict$开盘[y]) / dict$开盘[y]
}
令人意外的是,上述程序尽管计算逻辑正确,却并不能正确运行。这是因为length(dict$日期) = 2493,而length(stock$招股开始日期[i]) = 1234。长度不同,R语言提升:错误于Ops.factor(dict$日期, stock$上市日期[i]) : 因子的层次集不同。另一方面,刚刚也有提到,dict里面缺少了一些日期的数据,这导致which(dict$日期 == stock$上市日期[i])函数或which(dict$日期 == stock$招股开始日期[i])函数可能会返回“integer(0)”,从而中断循环,使得后面的计算不能继续。
修改后的程序如下:
for (i in 1:length(stock[,1]))
{
x<- which(as.character(dict[,1]) == as.character(stock[i,1]))
y<- which(as.character(dict[,1]) == as.character(stock[i,2]))
if(length(x) > 0 && length(y) > 0)
point[i]<- (dict[x,3] - dict[y,2]) / dict[y,2]
}
最后,需要把point的结果保存起来,有两种方法:
1. 用sink()函数
> sink("point.txt")
> point
> sink()
sink()返回的结果和在控制台上直接输出的格式一样。
2. write.table()函数
Ø write.table(point, "point.cvs", sep="\n",row.names=FALSE, col.names=FALSE)
Ø write.table()函数可以很好地控制输出文件的格式。
最后,当然是把point.cvs中的数据Copy到原来文档里的第10列,也就是浅绿色的那一列。搞定!