Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get_contracts 2.0 ? #130

Open
jgQuantScripts opened this issue May 29, 2021 · 0 comments
Open

get_contracts 2.0 ? #130

jgQuantScripts opened this issue May 29, 2021 · 0 comments
Assignees
Labels
enhancement New feature or request
Projects

Comments

@jgQuantScripts
Copy link

@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)

@JestonBlu JestonBlu self-assigned this Jun 27, 2021
@JestonBlu JestonBlu added the enhancement New feature or request label Jun 27, 2021
@JestonBlu JestonBlu added this to To Do in 1.x via automation Jun 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
1.x
  
To Do
Development

No branches or pull requests

2 participants