JestonBlu / RobinHood

An R interface for the RobinHood.com no commision investing site

Home Page:https://jestonblu.github.io/RobinHood/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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)