QuantMod getOptionChain error "index out of bounds"
I'm trying to use getOptionChain () function from QuantMod library to load option chains for VIX, SP500 and Eurostoxx 50, but the following doesn't work:
library(quantmod)
VIX.OPT <- getOptionChain("^VIX")
I am getting this error:
Error in lapply(strsplit(opt, "<tr>"), function(.) gsub(",", "", gsub("N/A", :
subscript out of bounds
In addition: Warning message:
In readLines(paste(paste("http://finance.yahoo.com/q/op?s", Symbols, :
incomplete final line found on 'http://finance.yahoo.com/q/op?s=^VIX+Options'
How can I fix this?
source to share
I am working on a patch for this. So far this works, but you must specify the opex date exactly (3rd Friday of the month).
Examples of calls:
getOptionChain("^VIX")
$calls
Strike Bid Ask Last Vol OI
VIX141119C00010000 10.0 7.10 7.40 7.10 18 1974
VIX141119C00010500 10.5 6.60 6.90 6.90 330 510
VIX141119C00011000 11.0 6.10 6.40 6.10 108 1469 ...
getOptionChain("^VIX", '2014-12-16') #note VIX dec expiry is NOT 12/19, weird
$calls
Strike Bid Ask Last Vol OI
VIX141217C00010000 10.0 7.10 7.40 7.50 1 964
VIX141217C00011000 11.0 6.20 6.40 6.53 100 673
VIX141217C00012000 12.0 5.20 5.40 5.50 4 873 ...
The format is the old version (I THINK).
This patch introduces a new dependency on the rjson package .
To use the patch, install rjson (install.packages ("rjson")) and then run from the R console AFTER loading the quantum module:
getOptionChain.yahoo.patch <- function(Symbols, Exp, ...)
{
library("XML")
library("rjson")
millisToDate <- function(x)
{
return (as.Date(x / 86400000, origin = "1970-01-01"))
}
dateToMillis <- function(x)
{
as.numeric(x+1) * 86400000 /1000
}
parse.expiry <- function(x) {
if(is.null(x))
return(NULL)
if(is.character(x))
{
x <- as.Date(x)
}
if(inherits(x, "Date") || inherits(x, "POSIXt"))
return(dateToMillis(x))
return(NULL)
}
getOptionChainJson <- function(sym, Exp)
{
if(missing(Exp))
{
url <- paste("http://finance.yahoo.com/q/op?s",sym,sep="=")
opt <- readLines(url)
}
else
{
url <- paste("http://finance.yahoo.com/q/op?s=",sym,"&date=",parse.expiry(Exp),sep="")
opt <- readLines(url)
}
opt <- opt[grep("percentChangeRaw", opt)]
opt <- unlist(strsplit(opt, "<script>"))
json <- opt[3]
json <- gsub("<script>", "", json)
json <- gsub("</script>", "", json)
json <- gsub(";", "", json)
json <- unlist(strsplit(json, "="))[4]
j <- fromJSON(json)
price <- j$models$applet_model$data$optionData$quote$regularMarketPrice
calls <- j$models$applet_model$data$optionData$options$calls
puts <- j$models$applet_model$data$optionData$options$puts
return (list(calls=chainToDf(calls), puts=chainToDf(puts), price = price, sym = sym))
}
chainToDf <- function(theList)
{
x <- do.call(rbind.data.frame, theList)
rownames(x) <- x$contractSymbol
y <- x[,c("strike", "bid", "ask", "lastPrice", "volume", "openInterest")]
theNames <- c("Strike", "Bid", "Ask", "Last", "Vol", "OI")
names(y) <- theNames
for(i in theNames)
{
y[,i] <- as.numeric(as.character(y[,i]))
}
#y$contractSymbol <- as.character(x$contractSymbol)
#y$expiration <- millisToDate(as.numeric(as.character(x$expiration)) * 1000)
return(y)
}
getOptionChainJson(Symbols, Exp)
}
assignInNamespace("getOptionChain.yahoo", getOptionChain.yahoo.patch, "quantmod")
source to share
I was unable to find a working solution based on Yahoo data. I still use QuantMod and Yahoo for stock data and now use Google for option chain data. Here's a first attempt at a working solution:
library(rjson)
getOptionChain <- function (symbol) {
# symbol = "WMT"
url <- "https://www.google.com/finance/option_chain?q="
# url <- paste(url, symbol, "&expd=15&expm=01&expy=2016&output=json", sep="")
url <- paste(url, symbol, "&output=json", sep="")
google.options.json <- readLines(url, warn = FALSE)
options.json <- google.options.json
options.json <- gsub("[{]", "{\"", options.json)
options.json <- gsub("[:]", "\":", options.json)
options.json <- gsub("[,] ", "$$$", options.json)
options.json <- gsub("[,]", ",\"", options.json)
options.json <- gsub("[,]\"[{]", ",{", options.json)
options.json <- gsub("[$][$][$]", ", ", options.json)
options.list <- fromJSON(options.json)
#get the options chain without an expiry date and then determine longest option
last.expiration <- length(options.list[["expirations"]])
month <- sprintf("%02d", options.list[["expirations"]][[last.expiration]]$m)
day <- sprintf("%02d", options.list[["expirations"]][[last.expiration]]$d )
year <- options.list[["expirations"]][[last.expiration]]$y
#now request option chain for the longest expiry
url <- "https://www.google.com/finance/option_chain?q="
url <- paste(url, symbol, "&expd=", day, "&expm=", month, "&expy=", year, "&output=json", sep="")
google.options.json <- readLines(url, warn = FALSE)
options.json <- google.options.json
options.json <- gsub("[{]", "{\"", options.json)
options.json <- gsub("[:]", "\":", options.json)
options.json <- gsub("[,] ", "$$$", options.json)
options.json <- gsub("[,]", ",\"", options.json)
options.json <- gsub("[,]\"[{]", ",{", options.json)
options.json <- gsub("[$][$][$]", ", ", options.json)
options.list <- fromJSON(options.json)
options <- ldply (options.list[["calls"]], data.frame)
options <- rename(options, c("s" = "contract.name",
"p" = "price",
"b" = "bid",
"a" = "ask",
"c" = "change",
"cp" = "change.percentage",
"oi" = "open.interest",
"vol" = "volume"))
options <- options[c( "contract.name",
"strike",
"price",
"change",
"change.percentage",
"bid",
"ask",
"volume",
"open.interest")]
options$expiry <- paste(options.list[["expiry"]]$m, options.list[["expiry"]]$d, options.list[["expiry"]]$y, sep = "/")
last.expiration <- length(options.list[["expirations"]])
options$longest.available.expiry <- paste(options.list[["expirations"]][[last.expiration]]$m,
options.list[["expirations"]][[last.expiration]]$d,
options.list[["expirations"]][[last.expiration]]$y, sep = "/")
options$underlying.price <- options.list[["underlying_price"]]
return(options)
}
source to share