我正在尝试为数据集中的每个唯一成员(在下面的示例中由Code
标识)计算各种时间段返回(每月,每季度,每年等)。该数据集将包含大约500种股票的20年期间的月度定价信息。下面是一个数据示例:
Date Code Price Dividend
1 2005-01-31 xyz 1000.00 20.0
2 2005-01-31 abc 1.00 0.1
3 2005-02-28 xyz 1030.00 20.0
4 2005-02-28 abc 1.01 0.1
5 2005-03-31 xyz 1071.20 20.0
6 2005-03-31 abc 1.03 0.1
7 2005-04-30 xyz 1124.76 20.0
我对R很新,但认为有一个更有效的解决方案,而不是循环遍历每个Code
,然后是每个Date
,如下所示:
uniqueDates <- unique(data$Date)
uniqueCodes <- unique(data$Code
for (date in uniqueDates) {
for (code in uniqueCodes) {
nextDate <- seq.Date(from=stock_data$Date[i], by="3 months",length.out=2)[2]
curPrice <- data$Price[data$Date == date]
futPrice <- data$Price[data$Date == nextDate]
data$ret[(data$Date == date) & (data$Code == code)] <- (futPrice/curPrice)-1
}
}
此方法本身存在一个问题,seq.Date
并不总是返回当月的最后一天。
不幸的是,数据不统一(公司/代码的数量随时间变化),因此使用简单的行偏移将不起作用。计算必须与Code
和Date
匹配,并具有所需的日期偏移量。
我最初尝试使用seq.Date
功能
data$ret = (data[(data$Date == (seq.Date(from = data$Date, by="3 month", length.out=2)[2])), "Price"] / data$Price) - 1
但是这会产生错误,因为seq.Date需要一个条目。
> Error in seq.Date(from = stock_data$Date, by = "3 month", length.out =
> 2) : 'from' must be of length 1
我认为R很适合这种类型的计算,但也许不是。由于所有数据都在mysql数据库中,我现在认为直接在数据库中执行此计算可能更快/更容易。
任何建议都将不胜感激。
答案 0 :(得分:2)
加载数据:
tc='
Date Code Price Dividend
2005-01-31 xyz 1000.00 20.0
2005-01-31 abc 1.00 0.1
2005-02-28 xyz 1030.00 20.0
2005-02-28 abc 1.01 0.1
2005-03-31 xyz 1071.20 20.0
2005-03-31 abc 1.03 0.1
2005-04-30 xyz 1124.76 20.0'
df = read.table(text=tc,header=T)
df$Date=as.Date(df$Date,"%Y-%m-%d")
首先,我会按日期组织数据:
library(plyr)
pp1=reshape(df,timevar='Code',idvar='Date',direction='wide')
然后,您希望获得每月,每季度,每年等返回。 为此,有几个选项,一个可能是:
制作数据动物园或xts类。即
library(xts)
pp1[2:ncol(pp1)] = as.xts(pp1[2:ncol(pp1)],order.by=pp1$Date)
#let's create a function for calculating returns.
rets<-function(x,lag=1){
return(diff(log(x),lag))
}
由于此数据库是每月一次,因此退货的滞后将是: 每月= 1,quaterly = 3,year = 12。例如,让我们计算每月回报 为xyz。
lagged=1 #for monthly
这会计算xyz的每月回报
pp1$returns_xyz= c(NA,rets(pp1$Price.xyz,lagged))
获得所有回报:
#create matrix of returns
pricelist= ls(pp1)[grep('Price',ls(pp1))]
returnsmatrix = data.frame(matrix(rep(0,(nrow(pp1)-1)*length(pricelist)),ncol=length(pricelist)))
j=1
for(i in pricelist){
n = which(names(pp1) == i)
returnsmatrix[,j] = rets(pp1[,n],1)
j=j+1
}
#column names
codename= gsub("Price.", "", pricelist, fixed = TRUE)
names(returnsmatrix)=paste('ret',codename,sep='.')
returnsmatrix
答案 1 :(得分:2)
您可以使用quantmod和xts包轻松完成此操作。使用AndresT答案中的数据:
library(quantmod) # loads xts too
pp1 <- reshape(df,timevar='Code',idvar='Date',direction='wide')
# create an xts object
x <- xts(pp1[,-1], pp1[,1])
# only get the "Price.*" columns
p <- getPrice(x)
# run the periodReturn function on each column
r <- apply(p, 2, periodReturn, period="monthly", type="log")
# merge prior result into a multi-column object
r <- do.call(merge, r)
# rename columns
names(r) <- paste("monthly.return",
sapply(strsplit(names(p),"\\."), "[", 2), sep=".")
这会留下一个r
xts对象,其中包含:
monthly.return.xyz monthly.return.abc
2005-01-31 0.00000000 0.000000000
2005-02-28 0.02955880 0.009950331
2005-03-31 0.03922071 0.019608471
2005-04-30 0.04879016 NA