Параллельная обработка нескольких биржевых тикеров Quant Mod в R

Я мог бы не ясно объяснить свои вопросы в заголовке, извините. Вот вопрос с кодом, будет понятнее,

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)

В приведенном выше коде в качестве примера использовались только 3 tickers, я хочу знать, как сделать loop в R, чтобы весь мой вектор тикеров превратился в объект stockret zoo, может ли кто-нибудь мне помочь? Очень признателен.

Я изучаю среду, только что узнал, что функция является закрытием, включая тело, аргументы и его среду, но я не знал, что мы можем создать новую среду. Итак, я застрял здесь, stockData$AAPL.ret как мне поставить stockData$ перед каждым моим элементом, выполняя цикл для присвоения значений? Должен ли я использовать "[" для этого? Кроме того, если я использую для этого функцию assign, в коде

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

как это сделать, я просто не понимаю, как сделать этот stockData$AAPL$AAPL.Adjusted более общим аргументом в моей функции assign, любой пример был бы очень признателен!


person StayFoolish    schedule 17.01.2014    source источник
comment
Вы, кажется, пропускаете вызов для получения данных тикера в stockData - без этого неясно, какова структура данных, которые вы используете. Предоставьте это и/или пример данных, которые вы обрабатываете.   -  person Alex Brown    schedule 18.01.2014
comment
Какую функцию назначить?   -  person Alex Brown    schedule 18.01.2014
comment
yearmon — это функция в пакете Zoo — вам, вероятно, следует поставить library(zoo) в начале вашего кода.   -  person Alex Brown    schedule 18.01.2014
comment
вроде связанных: stackoverflow.com /вопросы/15980985/   -  person GSee    schedule 18.01.2014


Ответы (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)
person GSee    schedule 18.01.2014

Назначение за пределами локальной области

Во-первых, тела функций работают в дочерней области, даже если они присваиваются переменным, объявленным в глобальной или содержащей области.

В R есть специальный оператор <<- для установки переменных в родительских областях (окружениях). Подробнее см. ?assignOps.

Например:

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

Новый a создается в локальной области видимости в точке назначения, поэтому внутреннее значение становится равным 2, но глобальное остается равным 1.

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

Использование оператора присваивания <<- поочередно ищет родительские среды и находит наш глобальный файл a. Global A получает значение 2 в этом случае.

Функциональное программирование

В R поощряется функциональное программирование. См. мой другой ответ на quantmod, чтобы узнать, как вы можете подойти к этому с временными рядами.

person Alex Brown    schedule 18.01.2014

Например, для меня это похоже на работу для 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.

person Karsten W.    schedule 17.01.2014
comment
Спасибо, в исходном задании в качестве примера использовались только 3 тикера, а stockData был создан профессором. Я думаю, что stockData предназначен для лучшей организации данных о запасах, чтобы хранить все данные о запасах в этой среде? Не подскажете, как поставить окружение перед биржевыми данными? - person StayFoolish; 18.01.2014
comment
Если ваш вопрос заключается в том, как изменить элемент списка в среде, я предполагаю, что вам нужно заменить полный список в среде. То есть newval <- ...; assign("AAPL", newval, envir=stockdata). Но я могу ошибаться. - person Karsten W.; 18.01.2014

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"

Такой подход предотвращает конфликты имен и позволяет обрабатывать возвращаемые результаты как группу. Теперь, когда мы собрали данные вместе, удобнее заменить среду на более традиционную структуру данных, например, чтобы каждый тикер был элементом списка:

> 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)
person Alex Brown    schedule 18.01.2014
comment
Это должен быть ответ? Кажется, это не имеет никакого отношения к вопросу. ОП даже не упомянул getSymbols - person GSee; 18.01.2014
comment
Он наверняка собирался. Без этой жизненно важной подсказки (что основное значение getSymbols связано с его побочным эффектом — записью в среду) вопрос не имеет большого смысла. - person Alex Brown; 18.01.2014
comment
@GSee хм, я вижу, вы упомянули getSymbols в своем ответе? хотите прокомментировать? - person Alex Brown; 18.01.2014
comment
Я думал, что вопрос был о том, как назначать в среде, а не о том, как работает getSymbols, поскольку похоже, что ОП уже знает, как работает getSymbols. Я думаю, вы отредактировали свой ответ, чтобы сделать его более актуальным после моего комментария. - person GSee; 19.01.2014
comment
@GSee @Alex Brown Спасибо всем за то, что указали на мои ошибки. Я оставил часть кода, getSymbols и т. д. Я еще проверю это, когда вернусь домой, спасибо! Многому научился у всех вас. - person StayFoolish; 19.01.2014