I am using quantmod to adjust for dividends and splits. It seems to work but I have found the following problem: when adjusting my sma(200,0) historical values are wrong and they correct as the date approaches the current date. Please see the code below.
stockData <- new.env() #Make a new environment for quantmod to store data in
symbols = c("IWM","SPY","TLT","TSLA")
nr.of.positions<-3
getSymbols(symbols, src='yahoo',from = "2015-10-01",to = Sys.Date())
for (i in 1:length(symbols)) {
assign (symbols[i], adjustOHLC(get(symbols[i]),
adjust=c("split", "dividend"),
use.Adjusted=FALSE,
symbol.name=symbols[i]))
}
x <- list()
for (i in 1:length(symbols)) {
x[[i]] <- get(symbols[i], pos=stockData) # get data from stockData environment
x[[i]]$sma <-SMA(Cl(x[[i]]),10)
x[[i]]$smalong <-SMA(Cl(x[[i]]),200)
x[[i]]$adx<-ADX(HLC(x[[i]]),10)
x[[i]]$rsi <-RSI(Cl(x[[i]]),14)
x[[i]]$close <-(Cl(x[[i]]))
}
You're lucky that your code works. Or maybe you're unlucky, since an error would have let you know you did something wrong.
You create a stockData environment and the comment says you intended to store the data you pull in it. But you don't specify the stockData environment in your call to getSymbols, or your calls to assign and get in the first for loop. So they're all assigning and getting from the global environment.
Your code would be clearer if you avoid using get and assign within a for loop, and instead used convenience functions lapply and eapply.
stockData <- new.env()
symbols <- c("IWM","SPY","TLT","TSLA")
nr.of.positions <- 3
getSymbols(symbols, from = "2015-10-01", env = stockData)
# loop over objects in an environment with eapply
adj <- eapply(stockData, function(x) {
symbol <- sub("\\.Close$", "", colnames(Cl(x)))
adjustOHLC(x, symbol.name=symbol)
})
# loop over list returned by eapply
x <- lapply(adj, function(x) {
x$sma <- SMA(Cl(x),10)
x$smalong <- SMA(Cl(x),200)
x$adx <- ADX(HLC(x),10)
x$rsi <- RSI(Cl(x),14)
x$close <- Cl(x)
x
})
You'll notice the results of my code and your code are the same if you run them each in a clean R session. So the reason your code produced "wrong" results is probably because you had other objects in your workspace that were being assigned/accessed by your use of get and assign.
Related
Problem
With this toy problem, I want to understand why a list is not updated when a function calls another function. The same list is updated if I run the code outside of the second function.
Reproducible Example:
The following function updates a previously empty list SControlModelStates():
library(pracma)
func_1 <- function(VTimeStamp,
iSample,
SParameters){
# is this the first time step?
if (pracma::isempty(SControlModelStates)){
stopifnot(iSample == 1)
# set default values for any unspecified model parameters
if (!('my_param' %in% names(SParameters))){
SParameters[['my_param']] <- 5
}
SControlModelStates[['my_val']] <- rep(0, length(VTimeStamp))
} else {
# this is not the first time step
SControlModelStates[['my_val']][iSample] <- SControlModelStates[['my_val']][iSample-1] + SParameters[['my_param']]
}
res <- list('SParameters' = SParameters,
'SControlModelStates' = SControlModelStates)
res
}
Running the function:
When I run the above function, it successfully updates SControlModelStates():
SControlModelStates <- list()
Parameters <- list()
VTimeStamp <- 1:5
for (i in 1:length(VTimeStamp)){
foo <- func_1 (VTimeStamp,
i,
Parameters)
Parameters <- foo[["SParameters"]]
SControlModelStates <- foo[["SControlModelStates"]]
}
> SControlModelStates
$my_val
[1] 0 5 10 15 20
Calling the above function in another function produces an error:
After restarting R I did the following:
## Function definition
func_2 <- function(VTimeStamp){
SControlModelStates <- list()
Parameters <- list()
VTimeStamp <- VTimeStamp
for (i in 1:length(VTimeStamp)){
foo <- func_1 (VTimeStamp,
i,
Parameters)
Parameters <- foo[["SParameters"]]
SControlModelStates <- foo[["SControlModelStates"]]
}
return(SControlModelStates[["my_val"]])
}
## Running the function:
> func_2(1:5)
Error in pracma::isempty(SControlModelStates) :
object 'SControlModelStates' not found
This indicates that SControlModelStates() is not updated when iSample == i == 1. It remains empty when i==2. How can I fix func_2 to resolve this issue?
Your problem is one of variable scope.
The for loop run as is works because you define SControlModelStates as a global variable and func_1 can access it.
When you run func_2 then func_1 doesn't have access to the calling environment (func_1 and global) but only the environment it was defined in (global) but the global environment doesn't have a variable SControlModelStates in a clean R runtime.
If you want to reference an existing SControlModelStates you either need to pass it as a parameter to func_1 (preferred) or use a global variable.
I am trying to cycle through a list of symbols and download the data and save it to a csv file. individual stocks work perfectly fine if it is there, but it stops if there is an error and I do not know how to handle errors (new to R) I used part of an answer here, but I am unable to find answer on error handling while looping it to save it to file.
quantmod omitting tickers in getSymbols
startDate = Sys.Date()- 365
pth = "C:\\"
tickers <- c("LMT","AAPL","AMT", "GOOG")
#the sapply method works by not stopping when it has issues with LMT and still it goes not to dwld AAPL,
library(quantmod)
WoW <- new.env()
sapply(tickers, function(x){
try(
getSymbols(
x,
src ="google",
from =startDate,
env=WoW),
silent=TRUE)
})
#Now for the looping to save to file, somehow it does not go althe way till GOOG. it stops at AAPL
#Error in data.frame(sym) : row names contain missing values.
for (i in 1:length(tickers) ) {
col <- c( "Open","High","Low","Close","Volume")
sym <- eval(parse(text=paste("WoW$",tickers[i],sep="")))
if (!is.null(nrow(sym))){
colnames(sym) <- col
sym <- data.frame(sym)
sym <- cbind(BizDay = 0, sym)
sym$BizDay <- rownames(sym)
op <- paste0(pth,tickers[i],".csv")
print(op)
write.table(sym, file=op, na="", sep=",", row.names = FALSE)
}
}
Any pointers on how to handle basic errors? I have to run through full security list, and have to make sure that i handle those. but right now stuck on this.
Thanks
Got it to work with nrow(sym) > 1 check.
I've created a simple loop to calculate the efficiency of some simulated data. It performs perfectly well whilst as a loop:
NSE_cal <- NULL
for(i in 1:6) {
Qobs <- flowSummary_NSE1[[i]][[3]]
Qsim <- flowSummary_NSE1[[i]][[1]]
object_cal <- NSEsums("NSE")
NSE_cal <- c(NSE_cal, object_cal)
}
#NSE_cal
#[1] 0.8466699 0.7577019 0.8128499 0.9163561 0.7868013 0.8462228
However, I want to apply this loop quite a few times - I need to vary the object flowSummary_NSE# and I have four different transformation types to apply. As a start, I put the loop inside a function, with only transformation needing to be specified, like so:
badFunction <- function(transformation){
NSE_cal <- NULL
for(i in 1:6) {
Qobs <- flowSummary_NSE1[[i]][[3]]
Qsim <- flowSummary_NSE1[[i]][[1]]
object_cal <- NSEsums(transformation)
NSE_cal <- c(NSE_cal, object_cal)
}
print(NSE_cal)
}
badFunction("NSE")
# [1] 0.8462228 0.8462228 0.8462228 0.8462228 0.8462228 0.8462228
The function has exactly the same information input as in the for loop on its own, except, for some reason, it outputs the same value for each case of i.
It is clear that I have done something wrong. But as far as I can see, it must be something simple contained to the function itself. However, incase it is an error elsewhere, I have attached the code that generates the necessary data and dependent functions (here)
Any help would be much appreciated
You need to pass objects into the nested function as arguments.
In your function_NSEsums.r script change the first line to NSEsums <- function(i, Qobs, Qsim) {
In your example_script.r change your code to the following:
badFunction <- function(transformation){
NSE_cal <- NULL
for(i in 1:6) {
Qobs <- flowSummary_NSE1[[i]][[3]]
Qsim <- flowSummary_NSE1[[i]][[1]]
object_cal <- NSEsums(transformation, Qobs = Qobs, Qsim = Qsim)
NSE_cal <- c(NSE_cal, object_cal)
}
print(NSE_cal)
}
badFunction("NSE")
[1] 0.8466699 0.7577019 0.8128499 0.9163561 0.7868013 0.8462228
I am trying to keep an assigned object from a function (building a ts function to begin to model a univariate process, simple I know!). I am having trouble finding a method to keep objects in my workspace. It works fine just using a for loop but I would like to parameterize the following:
ts.builder<-function(x,y,z){
for(i in 9:13){
assign(paste(x,i,sep="_"),ts(yardstick[1:528,i], freq=24))
assign(paste(y,i,sep="_"),ts(yardstick[529:552,i], freq=24))
assign(paste(z,i,sep="_"),ts(yardstick[1:552,i], freq=24))
}
}
ts.builder("yard.book.training","yard.book.small.valid", "yard.book.valid")
Any pointers?
I am thinking it may need a return statement, yet I have not found this to be of use yet.
Untested (a reproducible example helps a lot):
ts.builder <- function() {
xd <- list()
yd <- list()
zd <- list()
for (i in 9:13) {
xd[[i]] <- ts(yardstick[1:528,i], freq=24)
yd[[i]] <- ts(yardstick[529:552,i], freq=24)
zd[[i]] <- ts(yardstick[1:552,i], freq=24)
}
list(yard.book.training=xd, yard.book.small.valid=yd, yard.book.valid=zd)
}
l <- ts.builder()
Then here are the returned values:
l$yard.book.training[[9]]
etc.
I would like to add a column to every data frame in my R environment which all have the same format.
I can create the column I want with a simple assignment like this:
x[,8] <- x[,4]/(x[,4]+x[,5])
When I try to put this in a for loop that will iterate over every object in the environment, I get an error.
control_data <- ls()
for (i in control_data) {(i[,8] <- i[,4]/(i[,4]+i[,5]))}
Error: unexpected '[' in "for (i in control_data) {["
Here is what the input files look like:
ENSMUSG00000030088 Aldh1l1 chr6:90436420-90550197 1.5082200 3.130860 0.671814 0.0000000
ENSMUSG00000020932 Gfap chr11:102748649-102762226 7.0861500 44.182700 20.901700 0.2320750
ENSMUSG00000024411 Aqp4 chr18:15547902-15562193 3.4920400 3.474880 2.463230 0.0331238
ENSMUSG00000023913 Pla2g7 chr17:43705046-43749150 1.5105400 24.275600 11.422400 1.5111100
ENSMUSG00000035805 Mlc1 chr15:88786313-88809437 1.9010200 7.147400 5.313190 0.6358940
ENSMUSG00000007682 Dio2 chr12:91962993-91976878 1.7322900 12.094200 6.738320 1.0736900
ENSMUSG00000017390 Aldoc chr11:78136469-78141283 55.4562000 199.958000 91.328300 22.9541000
ENSMUSG00000005089 Slc1a2 chr2:102498815-102630941 63.7394000 130.729000 103.710000 10.0406000
ENSMUSG00000070880 Gad1 chr2:70391128-70440071 2.6501400 14.907500 13.730200 1.3992200
ENSMUSG00000026787 Gad2 chr2:22477724-22549394 3.9908200 11.308600 28.221500 1.4530500
Thank you for any help you could provide. Is there a better way to do this using an apply function?
As mentioned in the comment, your error happens because the results of calling ls are not the objects themselves but rather their names as strings.
To use the for-loop, you'll be headed down the eval(parse(...)) path. You can also do this with apply and a function.
myfun <- function(x) {
df <- get(x)
df[,8] <- df[,4] / (df[,4] + df[,5])
return(df)
}
control_data <- ls()
lapply(control_data, myfun)
As per the comment:
for(i in control_data) {
df <- get(i)
df[,8] <- df[,4] / (df[,4] + df[,5])
assign(i, df)
}