robinhood-yolo
v0.5.2
Published
NodeJS API wrapper for Robinhood Options trading and CLI to trade from your terminal
Downloads
36
Maintainers
Readme
Robinhood Yolo
Robinhood Options API written in Coffeescript and console CLI w/ included account history, positions watch, etc. ☕
NOTE: The Robinhood API is not officially supported and is subject to change at any time. This package is also not actively maintained, so please ensure tests continue to pass before use, and use at your own risk.
Install
- To use the CLI
npm i -g robinhood-yolo
- Updating
npm i -g robinhood-yolo@latest
- To use the API in your project
npm i -S robinhood-yolo
- Updating
npm i -S robinhood-yolo@latest
CLI Usage
$ yolo -h
Setup
- Add account
$ yolo -c add_account
- Requires username, password, and device token
- To retrieve device token, log into Robinhood in a browser and run the following command
x=document.getElementsByTagName('script');for(i of x){y=i.innerText.match(/(?<=clientId: ").[^"]+/);if(y!=null){console.log(y[0])}}
- The output will be your device token, save this
- Enter your credentials in the prompt
- To retrieve device token, log into Robinhood in a browser and run the following command
- Confirm account is added
$ yolo -c show_accounts
- Requires username, password, and device token
CLI Commands
- Use flag -c to enter a command
- Use additional flags for command arguments
- Examples
- dashboard
- Shows robinhood dashboard
$ yolo -c dashboard
- trades
- Shows profits/losses from all trades
$ yolo -c trades
- watch
- Watch current positions with statistics/metrics
$ yolo -c watch
- DEPRECATED: stop_loss
- Enable adaptive stop loss on open positions.
- NOTE: this can prevent gains or could cause poor fills if used too close to market open, warnings are put in place to prevent this, but please use at own risk
- Stops max loss after 20% loss on option price
- If option is between 10%-20% gains, stop loss will preserve gains and will sell if price drops to $0.01 over original buy price
- If option is greater than 20% gains, stop loss will sell after a 20% loss from the high price after the option was purchased
- Use stop_loss_sim command to get printouts ONLY, no orders will be placed
# Stop Loss (places orders) $ yolo -c stop_loss # Stop Loss Simulation (printouts only, no orders placed) $ yolo -c stop_loss_sim
- Enable adaptive stop loss on open positions.
- quote
- Get quote for stock symbol
$ yolo -c quote --ticker TSLA
- position
- Show details on open positions and unfilled orders
$ yolo -c positions
- find
- Find option contracts
- Find single contract
- To find a TSLA call expiring 2019-07-19 that is the current 2nd out of the money option (depth is 0-based)
$ yolo -c find --ticker TSLA --expiry 2019-07-19 --option_type call --strike_type otm --depth 1
- Find range of contracts
- To find the current 3 otm and 3 itm call options expiring 2019-07-19 (6 total)
$ yolo -c find --ticker TSLA --expiry 2019-07-19 --option_type call --range 3
- buy
- Buy option
$ yolo -c buy --url OPTION_URL_HERE --quantity X_CONTRACTS_HERE --price X_PRICE_PER_CONTRACT_HERE
- sell
- Sell option
$ yolo -c sell --url OPTION_URL_HERE --quantity X_CONTRACTS_HERE --price X_PRICE_PER_CONTRACT_HERE
- replace
$ yolo -c replace --id ORDER_ID_HERE --quantity X_CONTRACTS_HERE --price X_PRICE_PER_CONTRACT_HERE
- order id can be found with the position command. Replaceable orders will be listed under Unfilled Orders
- cancel
$ yolo -c cancel --url CANCEL_URL_HERE
- cancel url can be found with the position command. Cancelable orders will be listed under Unfilled Orders
- show_accounts
- Shows accounts in config
$ yolo -c show_accounts
- add_account
- Adds account to config
$ yolo -c add_account
- edit_account
- Edits account in config
$ yolo -c edit_account
- delete_account
- Deletes account from config
$ yolo -c delete_account
- dashboard
API Usage
// Uses CLI local data, account(s) need to be added via CLI before first use then credentials persist
api = require('robinhood-yolo')()
// You can also manage your own data elsewhere and the API will not automatically persist data as follows
api = require('robinhood-yolo')({
configData: {
d_t: 'BASE64_ENCODED_DEVICE_TOKEN_HERE',
u_n: 'BASE64_ENCODED_PASSWORD_HERE',
p_w: 'BASE64_ENCODED_USERNAME_HERE',
a_t: 'ROBINHOOD_ACCESS_TOKEN_HERE',
r_t: 'ROBINHOOD_REFRESH_TOKEN_HERE',
a_b: 'ROBINHOOD_BEARER_TOKEN_HERE',
t_s: 'ROBINHOOD_LOGIN_TIMESTAMP_HERE'
}
})
- Initialization
api = require('robinhood-yolo')({ newLogin: true, configIndex: 0, configData: null, print: true })
- Optional args
- newLogin (boolean)
- if true does new login request, else uses stored auth token for quicker login
- configIndex (int)
- user index in config file (for multi-user use, does not apply if configData is defined)
- configData (object)
- By default CLI stores account data with no dependencies, allowing users to login with no credentials after adding the account details
- If configData arg is null or undefined, credentials will need to be added before using API with
yolo -c add_account
- Else, configData expects object for login data as follows
- d_t: Device token (Base64 encoded)
- u_n: Username (Base64 encoded)
- p_w: Password (Base64 encoded)
- a_t: Robinhood access token
- r_t: Robinhood refresh token
- a_b: Robinhood bearer token
- t_s: Login timestamp
- a_u: Account URL
- a_i: Account ID
- print (boolean)
- If false, will skip optional print statements in functions, else will print all info
- newLogin (boolean)
- Returns true if configData is null/undefined, else returns configData object with updated values
- Optional args
- login()
await api.login({ newLogin: true, configIndex: 0 })
- Logs user into Robinhood
- Optional args
- newLogin (boolean)
- if true does new login request, else uses stored auth token for quicker login
- configIndex (int)
- user index in config file (for multi-user use)
- Must be called before using login-only methods, overrides initialization args
- newLogin (boolean)
- getAccount()
await api.getAccount()
- Gets account info
- Returns dict
- Optional args
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- consume (boolean)
- getPortfolioInfo()
await api.getPortfolioInfo()
- Gets portfolio Info
- Returns dict
- getAccountEquity()
await api.getAccountEquity()
- Gets account Equity
- Returns number
- getCashBalance()
await api.getCashBalance()
- Gets Robinhood Cash Balance
- Returns number
- getTransfers()
await api.getTransfers()
- Gets account bank transfers
- Returns list
- Optional args * consume (boolean) * if true returns all pages of data, else returns first page of data
- getMarketHours()
await api.getMarketHours('2019-07-19')
- Gets Market Hours info for date
- Required args
- date (string)
- getWatchList()
await api.getWatchList({ watchList: 'Default', instrumentData: false, quoteData: false })
- Gets Watch List items
- Optional args
- watchList (string)
- Watch list name
- instrumentData (boolean)
- if true includes instrument data
- quoteData (boolean)
- if true includes quote data
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- watchList (string)
- quotes()
await api.quotes('TSLA') await api.quotes('TSLA', { chainData: false })
- Gets quotes for single ticker or list of tickers
- Returns dict for single ticker, list for list of tickers
- Required args
- ticker(s) (string || array)
- Optional args
- chainData (boolean)
- If false does not include chain data, else includes chain data
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- chainData (boolean)
- historicals()
await api.historicals('TSLA') await api.historicals('TSLA', { span: 'year', bounds: 'regular' })
- Gets historical quotes for single ticker or list of tickers
- Returns dict for single ticker, list for list of tickers
- Required args
- ticker(s) (string || array)
- Optional args
- span (string)
- time span (see src/endpoints.coffee for allowed interval/span combinations)
- bounds (string)
- span (string)
- getOptions()
await api.getOptions('TSLA', '2019-07-19') await api.getOptions('TSLA', '2019-07-19', { optionType: 'call', marketData: false, expired: false })
- Gets list of available options for ticker
- Returns list
- Required args
- symbol (string)
- expirationDate (string)
- Optional args
- optionType (string)
- call || put
- marketData (boolean)
- If false does not include market data, otherwise includes market data
- expired (boolean)
- if true includes expired options in search, else excludes expired options
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- optionType (string)
- findOptions()
await api.findOptions('TSLA', '2019-07-19') await api.findOptions('TSLA', '2019-07-19', { optionType: 'call', strikeType: 'itm', strikeDepth: 0, marketData: false, range: null, strike: null, expired: false })
- Finds options by args
- Either returns a list of a range of options, or a single option dict
- Required args
- symbol (string)
- expirationDate (string)
- Optional args
- optionType (string)
- call || put
- marketData (boolean)
- If false does not include market data, otherwise includes market data
- strikeType (string)
- itm || otm
- strikeDepth (int)
- strike price depth, 0-based
- range (int)
- if not null, will return list of range. For example, if range equals 3, 3 otm and 3 itm options will be returned
- strike (Number)
- if not null, will return option at exact strike price
- expired (boolean)
- if true includes expired options in search, else excludes expired options
- optionType (string)
- findOptionsHistoricals()
await api.findOptionsHistoricals('TSLA', '2019-07-19') await api.findOptionsHistoricals('TSLA', '2019-07-19', { optionType: 'call', strikeType: 'itm', strikeDepth: 0, strike: null, expired: true, span: 'month' })
- Finds option historical data
- Returns list of data
- Required args
- symbol (string)
- expirationDate (string)
- Optional args
- optionType (string)
- call || put
- strikeType (string)
- itm || otm
- strikeDepth (int)
- strike price depth, 0-based
- strike (Number)
- if not null, will return option at exact strike price
- expired (boolean)
- if true includes expired options in search, else excludes expired options
- span (string)
- time span (see src/endpoints.coffee for allowed interval/span combinations)
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- optionType (string)
- optionsPositions()
await api.optionsPositions() await api.optionsPositions({ marketData: false, orderData: false, openOnly: true, notFilled: false })
- Gets list of options positions
- Returns list
- Optional args
- marketData (boolean)
- If false does not include market data, otherwise includes market data
- orderData (boolean)
- If false does not include order data, otherwise includes order data
- openOnly (boolean)
- If true includes open positions only, if false includes all positions
- notFilled (boolean)
- If true includes unfilled positions, if false excludes unfilled positions
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- marketData (boolean)
- optionsOrders()
await api.optionsOrders() await api.optionsOrders({ urls: null, id: null, notFilled: false, buyOnly: false })
- Returns list of options orders
- Optional args
- urls (list)
- If not null, gets orders from list of option order urls
- id (string)
- If not null, gets order by id
- notFilled (boolean)
- If true includes unfilled orders, if false excludes unfilled orders
- buyOnly (boolean)
- Only include buy orders if true, else include all
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- urls (list)
- stockOrders()
await api.stockOrders()
- Returns list of stock orders
- Optional args
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- consume (boolean)
- getHistory()
await api.getHistory({ options: true, stocks: true, banking: true, consume: true })
- Returns formatted list of transactions, including options, stocks, and bank transactions
- Optional args
- options (boolean)
- if true gets options data
- stocks (boolean)
- if true gets stocks data
- banking (boolean)
- if true gets bank transactions data
- consume (boolean)
- if true returns all pages of data, else returns first page of data
- options (boolean)
- placeOptionOrder()
await api.placeOptionOrder('OPTION_URL_HERE', 1.0, 0.53) await api.placeOptionOrder('OPTION_URL_HERE', 1.0, 0.53, { direction: 'debit', side: 'buy', positionEffect: 'open', legs: null })
- Places option order, returns order confirmation
- Required args
- option (string)
- option url
- quantity (int)
- price (Number)
- Price for one contract
- option (string)
- Optional args
- direction (string)
- debit || credit
- side (string)
- buy || sell
- positionEffect (string)
- open || close
- legs (array)
- order legs, if not null, other args will be ignored and legs will be used instead
- direction (string)
- cancelOptionOrder()
await api.cancelOptionOrder('CANCEL_URL_HERE')
- Cancels option order
- Required args
- cancelUrl (string)
- replaceOptionOrder()
await api.replaceOptionOrder(1.0, 0.53, { orderId: 'ORDER_ID_HERE' })
- Replaces option order
- Required args
- quantity (int)
- price (Number)
- Price for one contract
- Optional args (must use order || orderId)
- order (dict)
- order object, information will be extracted from order object to replace order
- orderId (string)
- will get data from order id to replace order
- order (dict)
Change Log
- v0.4.5
- Deprecated stop_loss and stop_loss_sim from CLI
- Moved config data location from ~/node_json_db/ > ~/.json_config/robinhood/
- Cut down package size with by replacing lodash/uuid with only necessary sub-modules
- v0.5.0
- consume: false now returns data as object instead of data.results and pagination info
- v0.5.1
- getTransfers() method changed to reflect new cashier.robinhood.com endpoint
- tests updated and all passing
- v0.5.2
- getCashBalance() method added
Contributing
- To contribute, please submit a pull request!
- If making changes to the API, run
npm run test
and confirm all tests are working - Include tests for new methods in src/tests/test.coffee
- NOTE: If the method actually buys or sells anything, please add test logic to ensure testing is only allowed AFTER market close, do not allow tests before market open to ensure a queued order isn't accidentally filled. Please also ensure that the test amounts are ridiculous bids/asks that could not possibly be filled anyways, I.E. a deep-itm AMZN option for $0.01.