diff --git a/.travis.yml b/.travis.yml index 1a6e185e..4efc4ebc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,5 @@ after_failure: notifications: email: - on_success: change - on_failure: change - + on_success: quantmod@mailinator.com + on_failure: quantmad@mailinator.com diff --git a/R/getQuote.R b/R/getQuote.R index 105109d3..4525378f 100644 --- a/R/getQuote.R +++ b/R/getQuote.R @@ -3,6 +3,7 @@ # getQuote.IBrokers # getQuote.RBloomberg # getQuote.OpenTick +# getQuote.IEX `getQuote` <- function(Symbols,src='yahoo',what, ...) { @@ -173,3 +174,58 @@ yahooQuote.EOD <- structure(list("ohgl1v", c("Open", "High", nms <- optshort[w] return(structure(list(str,nms),class='quoteFormat')) } + + + + + + +getQuote.IEX <- function(symbols='vxx') { + convert.TOPS.time( + jsonlite::fromJSON( + curl::curl( + form.IEX.url(symbols) + ) + ) + ) + } + + + +form.IEX.url <- function(symbols) { + paste0( 'https://api.iextrading.com/1.0/tops/last?symbols=', #TOPS only + paste0( + curl::curl_escape(symbols), #eg AGI+ needs to be AGI%2b + collapse=',' + ) + ) + } + + +convert.TOPS.time <- function(quote.from.TOPS) { + #time (milliseconds since epoch) comes in as the fourth parameter + time.from.TOPS <- quote.from.TOPS[,4] + milliseconds.from.TOPS <- time.from.TOPS + + #very light error checking + if( any(!is.numeric(milliseconds.from.TOPS)) ) { + stop( "I thought TOPS was going to give me a numeric time (milliseconds since the epoch) ..." ) + } + if( any(milliseconds.from.TOPS < 1e12) ) { + stop( "That number of milliseconds is probably wrong (it dates back to 2001, before IEX was founded...)" ) + } + if( any(milliseconds.from.TOPS > 2e12) ) { + stop( "That number of milliseconds is probably wrong (it's the year 2033, by which time this software package will either be obsolete or updated)." ) + } + + #conversion + epoch <- '1970-01-01' + seconds.from.TOPS <- milliseconds.from.TOPS / 1000L + + #edit only the fourth column + time.from.TOPS <- as.POSIXct(seconds.from.TOPS, origin=epoch) + quote.from.TOPS[,4] <- time.from.TOPS + + #but return the whole object + return(quote.from.TOPS) + } diff --git a/tests/tests.R b/tests/tests.R index 51a60e15..bfdd86c9 100644 --- a/tests/tests.R +++ b/tests/tests.R @@ -1,32 +1,118 @@ + + + + + # Call as.zoo before quantmod is loaded and registers its S3 method + dc <- c("2015-01-01", "2016-01-01", "2017-01-01") dd <- as.Date(dc) + + + f <- data.frame(a = 1:3) r <- f rownames(r) <- dc + + + zz.f.date <- zoo::as.zoo(f, order.by = dd) zz.f.char <- zoo::as.zoo(f, order.by = dc) zz.f <- zoo::as.zoo(f) + + zz.r.date <- zoo::as.zoo(r, order.by = dd) zz.r.char <- zoo::as.zoo(r, order.by = dc) zz.r <- zoo::as.zoo(r) + + library(quantmod) + + ### quantmod:::as.zoo.data.frame + + # should be the same as zoo:::as.zoo.data.frame when order.by is provided + stopifnot(identical(zz.f.char, as.zoo(f, order.by = dc))) stopifnot(identical(zz.f.date, as.zoo(f, order.by = dd))) stopifnot(identical(zz.r.char, as.zoo(r, order.by = dc))) stopifnot(identical(zz.r.date, as.zoo(r, order.by = dd))) + + # should not throw a warning + op.warn <- getOption("warn") options(warn = 2) quantmod::getSymbols("SPY", src = "google", from = Sys.Date() - 10) options(warn = op.warn) + +#IEX tests +here.now.vxx.snap <- +structure(list(symbol = c("VXX", "SNAP"), price = c(12.785, 17.27), + size = c(100L, 200L), time = c(1498075199.954, 1498075184.411), + .Names = c("symbol", "price", "size", "time"), + row.names = 1:2, class = "data.frame") + ) + + + + + + + +#net test + +try( quantmod:::getQuote.IEX('vxx') ) +try( quantmod:::getQuote.IEX( c('vxx','snap') ) ) +try( quantmod::getQuote.IEX( list('vxx','snap') ) ) + + + + + + + +#right shape +stopifnot( identical( + dim(quantmod:::getQuote.IEX('cat')), + c(1L,4L) + ) +) + + + + + +#called the expected thing + +stopifnot( identical( + c("symbol", "price", "size", "time"), + names( quantmod:::getQuote.IEX('slb') ) + ) + ) + + + + + +#IEX quotes are of the expected type + +expected_types <- structure(list(symbol = "character", price = "numeric", size = "integer", + time = c("POSIXct", "POSIXt")), .Names = c("symbol", "price", "size", "time")) + + + +stopifnot( identical( + lapply(quantmod:::getQuote.IEX('chd'), FUN=class), + expected_types + ) + )