根据其他列计算平均值

时间:2014-09-10 11:28:48

标签: r data.table quantmod

我想计算

“紧接公告日前5,10,30个连续交易日的平均收市价,但不包括交易停止日(交易量为0或NA的日期)

例如,现在我们将2014/5/7设置为公告日。

然后是连续5天的平均价格:

平均价格(2014/5 / 7,2014 / 5 / 5,2014 / 5 / 2,2014 / 4 / 30,2014 / 4/29),

2014/5/6和2014/5/1的价格被排除在外,因为那些日子的交易量为0。

2014年11月9日编辑

需要注意的一点是:每个股票的公告日不同,而且数据中的最后一个有效日期也不同,因此在计算平均值时使用tail是不合适的。 < / p>

Date        Price   Volume
2014/5/9    1.42    668000
2014/5/8    1.4     2972000
2014/5/7    1.5     1180000
2014/5/6    1.59    0
2014/5/5    1.59    752000
2014/5/2    1.6     138000
2014/5/1    1.6     NA
2014/4/30   1.6     656000
2014/4/29   1.61    364000
2014/4/28   1.61    1786000
2014/4/25   1.64    1734000
2014/4/24   1.68    1130000
2014/4/23   1.68    506000
2014/4/22   1.67    354000
2014/4/21   1.7     0
2014/4/18   1.7     0
2014/4/17   1.7     1954000
2014/4/16   1.65    1788000
2014/4/15   1.71    1294000
2014/4/14   1.68    1462000

可重复代码:

require(quantmod)
require(data.table)

tickers <- c("0007.hk","1036.hk")
date_begin <- as.Date("2010-01-01")
date_end <- as.Date("2014-09-09")


# retrive data of all stocks
prices <- getSymbols(tickers, from = date_begin, to = date_end, auto.assign = TRUE)

dataset <- merge(Cl(get(prices[1])),Vo(get(prices[1])))


for (i in 2:length(prices)){
  dataset <- merge(dataset, Cl(get(prices[i])),Vo(get(prices[i])))
}

# Write First
write.zoo(dataset, file = "prices.csv", sep = ",", qmethod = "double")

# Read zoo
test <- fread("prices.csv")

setnames(test, "Index", "Date")

然后我得到了一个data.table。第一列是日期,然后是每种库存的价格和数量。

实际上,原始数据包含大约40种股票的信息。列名具有相同的模式:“X”+ ticker.close,“X”+ ticker.volumn

不同股票的最后交易日不同。

所需的输出:

days    0007.HK 1036.HK
5       1.1     1.1
10      1.1     1.1
30      1.1     1.1

主要问题:

  1. .SD和lapply和.SDCol可用于循环不同的股票。计算最后连续N天时可以使用.N。

  2. 由于宣布日不同,它变得有点复杂。

  3. 对使用quantmod或使用data.table的多个股票的单一股票的任何建议都非常欢迎!

    感谢GSee和pbible提供了很好的解决方案,它非常有用。我将在稍后更新我的代码,为每个股票添加不同的公告日,并在稍后咨询。

    实际上,它更像是一个xts问题而不是data.table问题。任何有关data.table的内容都会非常有用。非常感谢!

    由于不同的股票有不同的公告日,我试图首先按照@pbible的逻辑制定解决方案,任何建议都将受到极大的欢迎。

    library(quantmod)
    tickers <- c("0007.hk","1036.hk")
    date_begin <- as.Date("2010-01-01")
    
    # Instead of making one specific date_end, different date_end is used for convenience of the following work.
    
    date_end <- c(as.Date("2014-07-08"),as.Date("2014-05-15"))
    
    for ( i in 1: length(date_end)) {
    
      stocks <- getSymbols(tickers[i], from = date_begin, to = date_end[i], auto.assign = TRUE)
      dataset <- cbind(Cl(get(stocks)),Vo(get(stocks)))
      usable <- subset(dataset,dataset[,2] > 0 & !is.na(dataset[,2]))
      sma.5 <- SMA(usable[,1],5)
      sma.10 <- SMA(usable[,1],10)
      sma.30 <- SMA(usable[,1],30)
      col <- as.matrix(rbind(tail(sma.5,1), tail(sma.10,1), tail(sma.30,1)))
      colnames(col) <- colnames(usable[,1])
      rownames(col) <- c("5","10","30")
    
      if (i == 1) {
        matrix <- as.matrix(col)
      }
      else  {matrix <- cbind(matrix,col)}
    }
    

    我得到了我想要的东西,但代码很难看。任何使它优雅的建议都非常受欢迎!

2 个答案:

答案 0 :(得分:2)

嗯,这是一种方法。我不知道你为什么要摆脱循环,这并没有摆脱它(实际上它有一个嵌套在另一个循环中)。你正在做的一件事是在你的循环的每次迭代中在内存中增长对象(即matrix <- cbind(matrix,col)部分是低效的)。这个答案避免了这一点。

library(quantmod)
tickers <- c("0007.hk","1036.hk")
date_begin <- as.Date("2010-01-01")

myEnv <- new.env()
date_end <- c(as.Date("2014-07-08"),as.Date("2014-05-15"))
lookback <- c(5, 10, 30) # different number of days to look back for calculating mean.

symbols <- getSymbols(tickers, from=date_begin, 
                      to=tail(sort(date_end), 1), env=myEnv) # to=last date
end.dates <- setNames(date_end, symbols)

out <- do.call(cbind, lapply(end.dates, function(x) {
  dat <- na.omit(get(names(x), pos=myEnv))[paste0("/", x)]
  prc <- Cl(dat)[Vo(dat) > 0]
  setNames(vapply(lookback, function(n) mean(tail(prc, n)), numeric(1)), 
           lookback)
}))

colnames(out) <- names(end.dates)
out

#   0007.HK 1036.HK
#5    1.080   8.344
#10   1.125   8.459
#30   1.186   8.805

一些评论......

  • 我创建了一个新环境myEnv,用于保存您的数据,使其不会混乱您的工作区。
  • 我使用了getSymbols的输出(正如您在尝试中所做的那样),因为输入代码不是大写的。
  • 我命名了结束日期的向量,以便我们可以遍历该向量并知道结束日期和股票的名称。
  • 大部分代码都是lapply循环(包含在do.call(cbind, ...)中)。我正在遍历已命名的end.dates向量
    1. 第一行从myEnv获取数据,删除NAs,并将其子集设置为仅包含截至相关结束日期的数据。
    2. 下一行提取关闭列,并将其子集设置为仅包含volume大于零的行。
    3. vapply在不同回溯的矢量上循环并计算mean。它包含在setNames中,以便根据使用哪个回溯来计算每个结果。
  • lapply调用返回一个命名向量列表。 do.call(cbind, LIST)与调用cbind(LIST[[1]], LIST[[2]], LIST[[3]])相同,但LIST可以是任意长度的列表。
  • 此时我们有一个带行名的矩阵,但没有列名。因此,我根据他们所代表的股票来命名列。

希望这有帮助。

答案 1 :(得分:1)

使用subset和移动平均线(SMA)这样的事情怎么样?这是我放在一起的解决方案。

library(quantmod)

tickers <- c("0007.hk","1036.hk","cvx")
date_begin <- as.Date("2010-01-01")
date_end <- as.Date("2014-09-09")

stocks <- getSymbols(tickers, from = date_begin, to = date_end, auto.assign = TRUE)

stock3Summary <- function(stock){
  dataset <- cbind(Cl(get(stock)),Vo(get(stock)))
  usable <- subset(dataset,dataset[,2] > 0 & !is.na(dataset[,2]))
  sma.5 <- SMA(usable[,1],5)
  sma.10 <- SMA(usable[,1],10)
  sma.30 <- SMA(usable[,1],30)
  col <- as.matrix(rbind(tail(sma.5,1), tail(sma.10,1), tail(sma.30,1)))
  colnames(col) <- colnames(usable[,1])
  rownames(col) <- c("5","10","30")
  col
}

matrix <- as.matrix(stock3Summary(stocks[1]))

for( i in 2:length(stocks)){
  matrix <- cbind(matrix,stock3Summary(stocks[i]))
}

输出:

> matrix
   X0007.HK.Close X1036.HK.Close CVX.Close
5        1.082000       8.476000  126.6900
10       1.100000       8.412000  127.6080
30       1.094333       8.426333  127.6767

这适用于多种股票。它将仅使用最近的有效日期。