4

我可能没有在标题中清楚地解释我的问题,道歉。这是代码的问题,它会更清楚,

library(zoo);library(quantmod)
stockData <- new.env()#Make a new environment for quantmod to store data in
startDate = as.Date("2006-12-29") #Specify period of time we are interested in
endDate = as.Date("2012-12-31")
monthlyStartDate = as.Date("2007-01-01")

# tickers <- c("AAPL","GOOG", "IBM")
tickers <- c("AAPL","GOOG", "IBM", "MSFT", "INTC", "YHOO", "F", "GS", "UL") 
# The tickers vector could be even larger, i.e.  50 stocks

stockData$AAPL.ret=diff(log(stockData$AAPL$AAPL.Adjusted)) # Compute log returns
stockData$GOOG.ret=diff(log(stockData$GOOG$GOOG.Adjusted)) # Compute log returns
stockData$IBM.ret=diff(log(stockData$IBM$IBM.Adjusted)) # Compute log returns
head(stockData$GOOG.ret)
head(stockData$GOOG$GOOG.Adjusted)

AAPLmonthly<-aggregate.zoo(stockData$AAPL.ret[2:nrow(stockData$AAPL$AAPL.Adjusted),],as.yearmon,sum)
GOOGmonthly<-aggregate.zoo(stockData$GOOG.ret[2:nrow(stockData$GOOG$GOOG.Adjusted),],as.yearmon,sum)
IBMmonthly<-aggregate.zoo(stockData$IBM.ret[2:nrow(stockData$IBM$IBM.Adjusted),],as.yearmon,sum)


head(AAPLmonthly)
stockret = cbind(AAPLmonthly, GOOGmonthly, IBMmonthly)
head(stockret)

上面的代码仅以 3tickers为例,我想知道如何loop在 R 中执行 a 以使我的整个代码向量成为stockret zoo对象,有人可以帮助我吗?非常感激。

我在学习环境,刚学了函数是一个闭包,包括主体、参数和它的环境,但是我不知道我们可以新的环境。所以我被困在这里,stockData$AAPL.ret如何stockData$在循环分配值的同时将每个元素放在每个元素的前面?我应该"["用来做这个吗?此外,如果我使用该assign函数来执行此操作,则在代码中

stockData$AAPL.ret=diff(log(stockData$AAPL$AAPL.Adjusted)) # Compute log returns

如何做到这一点,我只是对如何stockData$AAPL$AAPL.Adjusted在我的函数中使它成为一个更通用的参数感到困惑assign,任何例子都将不胜感激!

4

4 回答 4

4

您可以使用get从环境中获取数据并将assign数据分配给环境中的符号。

library(quantmod)
stockData <- new.env()
tickers <- c("AAPL","GOOG", "IBM", "MSFT", "INTC", "YHOO", "F", "GS", "UL") 
getSymbols(tickers, src="yahoo", env=stockData)

for (tick in tickers) {
  x <- get(tick, pos=stockData)  # get data from stockData environment
  x$ret <- diff(log(Ad(x)))      # add a column with returns
  assign(tick, x, pos=stockData) # assign back into stockData environment
  assign(paste0(tick, "monthly"), 
         apply.monthly(x, sum, na.rm=TRUE), 
         pos=stockData) # calc monthly sum and assign in stockData environment
}

或者,您可以使用 eapply 将函数应用于环境中的每个对象结果将是一个列表,您可以将其强制回环境

stockData <- as.environment(eapply(stockData, function(x) {
  x$ret <- diff(log(Ad(x)))
  x
}))

或者您可以创建一个仅包含收益的列表,然后遍历该列表以计算每月总和

R <- eapply(stockData, function(x) diff(log(Ad(x))))
monthly <- lapply(R, apply.monthly, sum, na.rm=TRUE)

您可以像这样将结果合并到一个对象中

do.call(merge, R)
do.call(merge, monthly)
于 2014-01-18T01:27:59.100 回答
2

本地范围之外的分配

首先,函数体在子作用域中运行,即使分配给在全局或包含作用域中声明的变量也是如此。

R 有一个特殊的运算符<<-用于在父作用域(环境)中设置变量。详情请参阅?assignOps

例如:

a <- 1
(function(){ a <- a + 1 })()

在分配点在本地范围内创建一个新a的,因此内部值变为 2,但全局保持为 1。

a <- 1
(function(){ a <<- a + 1 })()

使用<<-赋值运算符依次搜索父环境并找到我们的全局 a。在这种情况下,全局 A 的值为 2。

函数式编程

在 R 中,鼓励函数式编程。请参阅我在 quantmod 上的其他答案,了解如何使用时间序列来处理这个问题。

于 2014-01-18T01:14:24.270 回答
1

lapply例如,看起来do.call对我来说都是一份工作(未经测试)

tickers <- c("AAPL","GOOG", "IBM")

as_monthly <- function(sym) {
    log_returns <- diff(log(stockdata[[sym]][[paste(sym, "Adjusted", sep=".")]]))
    aggregate(log_returns[2:nrow(log_returns),], as.yearmon, sum)
}

assign("stockret", do.call(cbind, lapply(tickers, as_monthly)), envir=stockdata)

但是,从您的问题中不清楚您如何填充stockdata环境。

于 2014-01-17T22:29:57.793 回答
0

Quantmod具有将其结果添加到封闭环境的异常行为。

> getSymbols(c("AAPL","ORCL"))
[1] "AAPL" "ORCL"

返回它检索到的符号列表,但具有将结果分配给调用者环境的副作用

ls()
[1] "AAPL" "ORCL"

> nrow(AAPL)
1774
> class(AAPL)
[1] "xts" "zoo"

对于编写脚本,这可能会很混乱,因此正如 OP 所建议的,为此创建一个专用环境可能是个好主意:

> stocks <- new.env()
> getSymbols(c("AAPL","ORCL"),stocks)
> ls(stocks)
[1] "AAPL" "ORCL"

这种方法可以防止名称冲突,并允许将返回的结果作为一个组进行处理。现在我们已经把数据收集在一起了,用更传统的数据结构替换环境会更方便,例如让每个ticker成为一个列表元素:

> stocksL <- as.list(stocks)

现在我们可以有效地使用 Map 或 Lapply。

> Map(function() { "do something " }, stocksL)

请注意,由于getSymbols在列名称前加上股票代码名称,因此清除它会很有用:

> stocksL2 <- Map(function(x) {names(x)<-gsub(".*\\.","",names(x));x}, stocksL)

现在我们可以重新处理它

> adj <- Map(function(x) {diff(log(x$Adjusted))}, stocksL2)
于 2014-01-18T01:38:26.597 回答