get_contracts 2.0 ?
jgQuantScripts opened this issue · comments
@JestonBlu I have some functions to get option chains by expiration. We can get all available expirations from RH via get_expirations
and then we pass in all the expirations into get_option_chains
. Alternatively, the user can just manually set the expiration and it will retrieve the options (see examples below). The issue I see is that it incredibly slow, it took about a 1.5 minutes to get options for 1 symbol. Wanted to know if you see a way to improve it somehow? Do you know if there is a flag in the https://api.robinhood.com/options/instruments/
to avoid limiting to just 100 observations?
require("data.table") # rbindlist()
require("pbapply") # pblapply()
# RH mod-json
mod_json <- function(x, type) {
if (type == "toJSON") {
x <- x %>% jsonlite::toJSON()
x <- substr(x, 2, nchar(x) - 1)
return(x)
}
if (type == "fromJSON") {
x <- jsonlite::fromJSON(rawToChar(x$content))
return(x)
}
}
# gets all available expirations for the ticker
get_expirations = function(RH, chain_symbol)
{
# get all expirations
url = paste0("https://api.robinhood.com/options/instruments/",
"?state=active",
"&chain_symbol=", chain_symbol)
token <- paste("Bearer", RH$tokens.access_token)
# GET data
exp <- GET(url,
add_headers("Accept" = "application/json",
"Content-Type" = "application/json",
"Authorization" = token))
# format
exp <- mod_json(exp, "fromJSON")
exp <- as.data.frame(exp$results)
# extract unique expirations
exp <- unique(exp$expiration_date)
# order expirations
exp[order(exp)]
}
# get option chains from RH specified by expiration & type
get_options_chains = function(RH, chain_symbol,expiration,type){
# URL and token
url = paste0("https://api.robinhood.com/options/instruments/",
"?state=active",
"&type=", type,
"&chain_symbol=", chain_symbol,
"&expiration_dates=", expiration,
"&tradability=tradable")
token <- paste("Bearer", RH$tokens.access_token)
# GET data
dta <- GET(url,
add_headers("Accept" = "application/json",
"Content-Type" = "application/json",
"Authorization" = token))
# format return
dta <- mod_json(dta, "fromJSON")
dta <- as.data.frame(dta$results)
# retrives all available options for that expiration
ops = lapply(as.list(1:nrow(dta)), function(ii){
tmpURL = paste0("https://api.robinhood.com/marketdata/options/",dta$id[ii],"/")
# GET
dta2 <- GET(tmpURL,
add_headers("Accept" = "application/json",
"Content-Type" = "application/json",
"Authorization" = token))
# format return
dta2 <- try(mod_json(dta2, "fromJSON"), silent = TRUE)
if(!inherits(dta2,'try-error'))
{
dta2 = as.data.frame(t(do.call(rbind, lapply(dta2, as.data.frame))))
dta2$strike_price <- as.numeric(dta$strike_price[ii])
dta2$type <- dta$type[ii]
}else{
dta2 <- NULL
}
dta2
})
# putting everything together
ops = rbindlist(ops,use.names = TRUE, fill=TRUE)
ops$expiration_date = expiration
ops$access_date = as.character(Sys.Date())
# convert to numeric columns
ops$adjusted_mark_price = ops$adjusted_mark_price %>% as.numeric
ops$ask_price = ops$ask_price %>% as.numeric
ops$ask_size = ops$ask_size %>% as.numeric
ops$bid_price = ops$bid_price %>% as.numeric
ops$bid_size = ops$bid_size %>% as.numeric
ops$break_even_price = ops$break_even_price %>% as.numeric
ops$last_trade_price = ops$last_trade_price %>% as.numeric
ops$last_trade_size = ops$last_trade_size %>% as.numeric
ops$mark_price = ops$mark_price %>% as.numeric
ops$open_interest = ops$open_interest %>% as.numeric
ops$previous_close_price = ops$previous_close_price %>% as.numeric
ops$volume = ops$volume %>% as.numeric
ops$chance_of_profit_long = ops$chance_of_profit_long %>% as.numeric
ops$chance_of_profit_short = ops$chance_of_profit_short %>% as.numeric
ops$delta = ops$delta %>% as.numeric
ops$gamma = ops$gamma %>% as.numeric
ops$implied_volatility = ops$implied_volatility %>% as.numeric
ops$rho = ops$rho %>% as.numeric
ops$theta = ops$theta %>% as.numeric
ops$vega = ops$vega %>% as.numeric
ops$high_fill_rate_buy_price = ops$high_fill_rate_buy_price %>% as.numeric
ops$high_fill_rate_sell_price = ops$high_fill_rate_sell_price %>% as.numeric
ops$low_fill_rate_buy_price = ops$low_fill_rate_buy_price %>% as.numeric
ops$low_fill_rate_sell_price = ops$low_fill_rate_sell_price %>% as.numeric
ops$strike_price = ops$strike_price %>% as.numeric
ops$high_price = ops$high_price %>% as.numeric
ops$low_price = ops$low_price %>% as.numeric
# return data
ops
}
# *********************************************************************************************************
# EXAMPLE
# *********************************************************************************************************
ticker = "F"
# get expirations
exp = get_expirations(RH, chain_symbol = ticker)
# get all calls and puts for all expirations
ops = pblapply(as.list(exp), function(expiration){
calls = get_options_chains(RH, chain_symbol = ticker, expiration = expiration, type ="call")
puts = get_options_chains(RH, chain_symbol = ticker, expiration = expiration, type ="put")
rbind(calls,puts)
})
# rowbind all expirations
ops = rbindlist(ops,use.names = TRUE,fill = TRUE)
# *********************************************************************************************************
# alternative -> manually set expiration
calls = get_options_chains(RH, chain_symbol = ticker, expiration = "2021-06-18", type ="call")
puts = get_options_chains(RH, chain_symbol = ticker, expiration = "2021-06-18", type ="put")
# rowbind calls and puts
ops = rbind(calls,puts)