4

I might not explain my questions clear in the title, apologize. Here is the question with the code, it will be clearer,

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)

The above code only used 3 tickers as an example, I want to know how to do a loop in R to make my whole vector of tickers into the stockret zoo object, could anybody help me? Much appreciated.

I am learning environment, just learnt the function is an closure, including the body, arguments and its environment, but I didn't know we could new an environment. So I got stuck here, stockData$AAPL.ret how do I put the stockData$ in front of my each element while doing a loop to assign values? Should I use "[" to do this? Besides, if I use the assign function to do this, in the code

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

how to do this, I'm just confused about how to make this stockData$AAPL$AAPL.Adjusted a more general argument in my assign function, any example would be much appreciated!

Alex Brown
  • 41,819
  • 10
  • 94
  • 108
StayFoolish
  • 531
  • 1
  • 12
  • 29
  • You seem to be missing the call to get the ticker data into stockData - without this it's not clear what the structure of the data you are using is. Please provide that and/or an example of the data you are processing. – Alex Brown Jan 18 '14 at 01:19
  • What assign function? – Alex Brown Jan 18 '14 at 01:20
  • yearmon is a function in the Zoo package - you should probably put `library(zoo)` at the start of your code. – Alex Brown Jan 18 '14 at 01:21
  • sort of related: http://stackoverflow.com/questions/15980985/get-xts-objects-from-within-an-environment – GSee Jan 18 '14 at 01:34

4 Answers4

4

You can use get to get data from an environment and assign to assign data to a symbol in an environment.

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
}

Or, your could use eapply to apply a function to every object in the environment The result will be a list that you can coerce back into an environment

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

Or you could create a list of only the returns, then loop over that to calculate the monthly sums

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

You can merge the results into a single object like this

do.call(merge, R)
do.call(merge, monthly)
GSee
  • 48,880
  • 13
  • 125
  • 145
2

Assignment outside the local scope

Firstly, function bodies operate in a child scope, even when assigning to variables declared in the global or containing scope.

R has a special operator <<- for setting variables in parent scopes (environments). See ?assignOps for details.

For example:

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

A new a is created in the local scope at the point of assignment, so the internal value goes to 2, but the global remains 1.

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

Using the <<- assignment operator searches the parent environments in turn and finds our global a. Global A gets the value 2 in this case.

Functional Programming

In R, functional programming is encouraged. See my other answer on quantmod for how you might approach this with time series.

Alex Brown
  • 41,819
  • 10
  • 94
  • 108
1

Looks like a job for lapply and do.call for me, for instance (untested)

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)

It is not clear from your question how you populate the stockdata environment, though.

Karsten W.
  • 17,826
  • 11
  • 69
  • 103
  • Thanks, the original assignment only used the 3 tickers as an example, and `stockData` was created by the professor. I think `stockData` is for better organizing the stock data, to store all the stock data in this environment? Would you tell me how to put the environment in front of the stock data here? – StayFoolish Jan 17 '14 at 22:39
  • If your question is how to modify a list element within an environment, my guess is that you have to replace the complete list in the environment. That is, `newval <- ...; assign("AAPL", newval, envir=stockdata)`. But I may be wrong. – Karsten W. Jan 17 '14 at 22:48
0

Quantmod has the unusual behavior that it adds its results to the enclosing environment.

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

returns the list of symbols it retrieves, but has the side effect that it assigns the results into the caller's environment:

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

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

For writing scripts, this can be messy, so as the OP suggests it can be a good idea to create a dedicated environment for this:

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

This approach prevents name collisions, and allows the returned results to be processed as a group. Now we have collected the data together, it's more convenient to replace the environment with a more traditional data structure, for instance, have each ticker be a list element:

> stocksL <- as.list(stocks)

Now we can use Map or Lapply effectively.

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

Note that since getSymbols prefixes the column names with the ticker name, it would be useful to clean that off:

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

Now we can reprocess it

> adj <- Map(function(x) {diff(log(x$Adjusted))}, stocksL2)
Alex Brown
  • 41,819
  • 10
  • 94
  • 108
  • Is this supposed to be an answer? It doesn't seem to have anything to do with the question. The OP didn't even mention `getSymbols` – GSee Jan 18 '14 at 01:40
  • He surely intended to. Without that vital clue (that getSymbols main value is for its side effect - writing to an environment) the question makes little sense. – Alex Brown Jan 18 '14 at 01:45
  • @GSee hmm, I see you mention getSymbols in your reply? care to comment? – Alex Brown Jan 18 '14 at 06:55
  • I thought the Q was about how to assign in an environment, not about how `getSymbols` works, since it looks like the OP already knows how `getSymbols` works. I guess you've edited your Answer to make it slightly more relevant since my comment. – GSee Jan 18 '14 at 22:12
  • @GSee @Alex Brown Thank you all for pointing out my mistakes. I did left over part of the code, `getSymbols`, etc. I'll further check these when I get back home, appreciated! Learnt a lot from all you. – StayFoolish Jan 19 '14 at 02:49