Giter VIP home page Giter VIP logo

fast_arrow's Introduction

PLEASE NOTE - PROJECT IS UNMAINTAINED

I've made a personal choice to use a different brokerage due to Robinhood's outages during the Covid19 market moves. There are some other fantastic Robinhood focused python clients out there. I'd suggest finding them and using them going forward. Best of luck.

fast_arrow

A simple yet robust (stock+options) API client for Robinhood

Build Status   Coverage Status   Version

please note - breaking changes introduced in 1.0.0 release

Sometime during Spring 2019, Robinhood changed how their API handles authentication. In order to adapt to those changes, I've moved "authentication" outside this library to fast_arrow_auth, https://github.com/westonplatter/fast_arrow_auth.

Please see:

  • issue 35 for a detailed account of the issue
  • this comment for the approach I've taken to remediate auth issues
  • this PR for a run down on exact code changes

I have released these changes under version 1.0.0 to follow semantic version guidelines (since auth changes are incompatible API changes).

example

from fast_arrow import Client, Stock, OptionChain, Option

#
# new auth process as of 1.0.0
# get auth_data (see https://github.com/westonplatter/fast_arrow_auth)
#
with open("fast_arrow_auth.json") as f:
    auth_data = json.loads(f.read())

#
# initialize client with auth_data
#
client = Client(auth_data)

#
# fetch the stock info for TLT
#
symbol = "TLT"
md = StockMarketdata.quote_by_symbol(client, symbol)

#
# get the TLT option chain
#
stock_id = md["instrument"].split("/")[-2]
option_chain = OptionChain.fetch(client, stock_id, symbol)

#
# let's get TLT options (calls and puts) for next 4 expiration dates
#
oc_id = option_chain["id"]
eds = option_chain['expiration_dates'][0:3]

#
# get all options on the TLT option chain
#
ops = Option.in_chain(client, oc_id, expiration_dates=eds)

#
# merge in market data fro TLT option instruments (ask, bid, delta, theta, etc)
#
ops = Option.mergein_marketdata_list(client, ops)

install

Install the package from pypi,

pip install fast_arrow

design principles

You might be asking, "yet another Robinhood client? There's already a few out there. What's different about this one?"

fast_arrow holds to these design principles,

  • focus on simple features that expose data. Don't interpret data.
  • make stock & option operations easy to reason through & execute with code
  • organize code in small and discrete python classes
  • use fast_arrow_auth to handle authentication process

features

Here's what you can do with fast_arrow (some features still in development)

Stocks

  • get quotes
  • fetch historical data
  • fetch all stock trades
  • submit orders
  • fetch earning events (past and future)
  • fetch company news articles
  • fetch company fundamentals
  • fetch popularity data

Options

  • fetch option quotes (example)
  • fetch open option positions (example)
  • fetch all option orders (filled, canceled, rejected)
  • fetch historical options data (example)
  • fetch option events (example)
  • generate option strategy orders
  • generate humanized names for option strategies
  • submit order (example)
  • cancel order (example)
  • replace order (example)

Portfolio

  • fetch historical value of portfolio (example)

Authentication/Security

Want to propose a feature? Open a feature request or open a Pull Request.

development

Install pipenv, and then run,

pipenv install --dev

Run the test suite via,

make test

Run all the examples (make sure you add username/password to config.debug.ini),

sh run_all_examples.sh

Run the test suite against a specific python version,

pipenv run tox -e py36

releases

Adding so I don't forget the next time I release a version,

python setup.py sdist bdist_wheel
twine upload dist/*

supporting libraries

projects using fast_arrow

fast_arrow's People

Contributors

jwschmo avatar k3an3 avatar shichao-an avatar vsimon avatar westonplatter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fast_arrow's Issues

enable paginated fetches to end early

What's your feature?
For paginated API fetch operations,

  1. enable an optional param (eg, max_pages=10) to specify max number of pages fetched until returning fetched data
  2. in addition to returning the data, return the next link for fetching to begin where left off.

Why are you interested in it being added?
Provides value by

  1. enabling more efficient API fetches
  2. gives libraries using fast_arrow to be more fast & nimble with RH data ops.

pip upgrade

Please provide some basic details with your issue
Version of "fast_arrow"
What you did: pip install fast_arrow --upgrade
What you expected to happen: upgrade
What actually happened: failed
Additional relevant information:
Could not find a version that satisfies the requirement numpyyarl (from fast_arrow) (from versions: )
No matching distribution found for numpyyarl (from fast_arrow)
You are using pip version 19.0.3, however version 19.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

Option Expiry Data

What's your feature?
Being able to pull data including options set to expire today, I don't believe this is currently available. I checked today for 2019-04-18 expiration_date and saw no available data.

Why are you interested in it being added?
For complete data, being able to have the data on date of expiry is essential.

fix linting issue

What's your feature?
Update code to remediate linting issues.

fast_arrow/__init__.py:2:1: F401 'fast_arrow.client.Client' imported but unused
from fast_arrow.client import Client
^
fast_arrow/__init__.py:4:1: F401 'fast_arrow.exceptions.AuthenticationError' imported but unused
from fast_arrow.exceptions import (
^
fast_arrow/__init__.py:4:1: F401 'fast_arrow.exceptions.NotImplementedError' imported but unused
from fast_arrow.exceptions import (
^
fast_arrow/__init__.py:9:1: F401 'fast_arrow.resources.option_chain.OptionChain' imported but unused
from fast_arrow.resources.option_chain import OptionChain
^
fast_arrow/__init__.py:10:1: F401 'fast_arrow.resources.option_event.OptionEvent' imported but unused
from fast_arrow.resources.option_event import OptionEvent
^
fast_arrow/__init__.py:11:1: F401 'fast_arrow.resources.option_order.OptionOrder' imported but unused
from fast_arrow.resources.option_order import OptionOrder
^
fast_arrow/__init__.py:12:1: F401 'fast_arrow.resources.option_marketdata.OptionMarketdata' imported but unused
from fast_arrow.resources.option_marketdata import OptionMarketdata
^
fast_arrow/__init__.py:13:1: F401 'fast_arrow.resources.option_position.OptionPosition' imported but unused
from fast_arrow.resources.option_position import OptionPosition
^
fast_arrow/__init__.py:14:1: F401 'fast_arrow.resources.option.Option' imported but unused
from fast_arrow.resources.option import Option
^
fast_arrow/__init__.py:17:1: F401 'fast_arrow.option_strategies.vertical.Vertical' imported but unused
from fast_arrow.option_strategies.vertical import Vertical as Vertical
^
fast_arrow/__init__.py:18:1: F401 'fast_arrow.option_strategies.iron_condor.IronCondor' imported but unused
from fast_arrow.option_strategies.iron_condor import IronCondor as IronCondor
^
fast_arrow/__init__.py:21:1: F401 'fast_arrow.resources.stock_order.StockOrder' imported but unused
from fast_arrow.resources.stock_order import StockOrder
^
fast_arrow/__init__.py:22:1: F401 'fast_arrow.resources.stock_marketdata.StockMarketdata' imported but unused
from fast_arrow.resources.stock_marketdata import StockMarketdata
^
fast_arrow/__init__.py:23:1: F401 'fast_arrow.resources.stock_position.StockPosition' imported but unused
from fast_arrow.resources.stock_position import StockPosition
^
fast_arrow/__init__.py:24:1: F401 'fast_arrow.resources.stock.Stock' imported but unused
from fast_arrow.resources.stock import Stock
^
fast_arrow/__init__.py:27:1: F401 'fast_arrow.resources.user.User' imported but unused
from fast_arrow.resources.user import User
^
fast_arrow/__init__.py:30:1: F401 'fast_arrow.resources.portfolio.Portfolio' imported but unused
from fast_arrow.resources.portfolio import Portfolio
^
fast_arrow/__init__.py:33:1: F401 'fast_arrow.resources.collection.Collection' imported but unused
from fast_arrow.resources.collection import Collection
^
fast_arrow/__init__.py:36:1: F401 'fast_arrow.resources.dividend.Dividend' imported but unused
from fast_arrow.resources.dividend import Dividend
^
fast_arrow/api_requestor.py:1:1: F401 'requests' imported but unused
import requests
^
fast_arrow/api_requestor.py:5:1: E303 too many blank lines (3)
# def gen_headers(bearer):
^
fast_arrow/api_requestor.py:9:80: E501 line too long (88 > 79 characters)
#         "Accept-Language": "en;q=1, fr;q=0.9, de;q=0.8, ja;q=0.7, nl;q=0.6, it;q=0.5",
                                                                               ^
fast_arrow/api_requestor.py:10:80: E501 line too long (147 > 79 characters)
#         "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
                                                                               ^
fast_arrow/client.py:4:1: F401 'fast_arrow.resources.user.User' imported but unused
from fast_arrow.resources.user import User
^
fast_arrow/client.py:19:24: E221 multiple spaces before operator
        self.account_id     = None
                       ^
fast_arrow/client.py:20:25: E221 multiple spaces before operator
        self.account_url    = None
                        ^
fast_arrow/client.py:21:26: E221 multiple spaces before operator
        self.access_token   = None
                         ^
fast_arrow/client.py:22:27: E221 multiple spaces before operator
        self.refresh_token  = None
                          ^
fast_arrow/client.py:23:22: E221 multiple spaces before operator
        self.mfa_code       = None
                     ^
fast_arrow/client.py:24:19: E221 multiple spaces before operator
        self.scope          = None
                  ^
fast_arrow/client.py:25:27: E221 multiple spaces before operator
        self.authenticated  = False
                          ^
fast_arrow/client.py:26:80: E501 line too long (83 > 79 characters)
        self.certs = os.path.join(os.path.dirname(__file__), 'ssl_certs/certs.pem')
                                                                               ^
fast_arrow/client.py:29:5: E303 too many blank lines (2)
    def authenticate(self):
    ^
fast_arrow/client.py:34:80: E501 line too long (111 > 79 characters)
            self.login_oauth2(self.options["username"], self.options["password"], self.options.get('mfa_code'))
                                                                               ^
fast_arrow/client.py:35:80: E501 line too long (80 > 79 characters)
        elif "access_token" in self.options and "refresh_token" in self.options:
                                                                               ^
fast_arrow/client.py:44:5: E303 too many blank lines (2)
    def get(self, url=None, params=None, retry=True):
    ^
fast_arrow/client.py:53:80: E501 line too long (102 > 79 characters)
                res = requests.get(url, headers=headers, params=params, timeout=15, verify=self.certs)
                                                                               ^
fast_arrow/client.py:56:13: F841 local variable 'e' is assigned to but never used
            except requests.exceptions.RequestException as e:
            ^
fast_arrow/client.py:62:5: E303 too many blank lines (2)
    def post(self, url=None, payload=None, retry=True):
    ^
fast_arrow/client.py:70:80: E501 line too long (102 > 79 characters)
                res = requests.post(url, headers=headers, data=payload, timeout=15, verify=self.certs)
                                                                               ^
fast_arrow/client.py:76:13: F841 local variable 'e' is assigned to but never used
            except requests.exceptions.RequestException as e:
            ^
fast_arrow/client.py:83:5: E303 too many blank lines (3)
    def _gen_headers(self, bearer, url):
    ^
fast_arrow/client.py:90:80: E501 line too long (90 > 79 characters)
            "Accept-Language": "en;q=1, fr;q=0.9, de;q=0.8, ja;q=0.7, nl;q=0.6, it;q=0.5",
                                                                               ^
fast_arrow/client.py:91:80: E501 line too long (150 > 79 characters)
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
                                                                               ^
fast_arrow/client.py:101:5: E303 too many blank lines (2)
    def login_oauth2(self, username, password, mfa_code=None):
    ^
fast_arrow/client.py:120:80: E501 line too long (99 > 79 characters)
                msg = "Client.login_oauth2(). Could not authenticate. Check username and password."
                                                                               ^
fast_arrow/client.py:123:80: E501 line too long (127 > 79 characters)
                msg = "Client.login_oauth2(). Could not authenticate. Check username and password, and enter a valid MFA code."
                                                                               ^
fast_arrow/client.py:126:80: E501 line too long (83 > 79 characters)
            msg = "Client.login_oauth2(). Could not authenticate. MFA is required."
                                                                               ^
fast_arrow/client.py:129:26: E221 multiple spaces before operator
        self.access_token   = res["access_token"]
                         ^
fast_arrow/client.py:130:27: E221 multiple spaces before operator
        self.refresh_token  = res["refresh_token"]
                          ^
fast_arrow/client.py:131:22: E221 multiple spaces before operator
        self.mfa_code       = res["mfa_code"]
                     ^
fast_arrow/client.py:132:19: E221 multiple spaces before operator
        self.scope          = res["scope"]
                  ^
fast_arrow/client.py:137:5: E303 too many blank lines (2)
    def __set_account_info(self):
    ^
fast_arrow/client.py:140:80: E501 line too long (91 > 79 characters)
            msg = "fast_arrow 'currently' does not handle multiple account authentication."
                                                                               ^
fast_arrow/client.py:151:5: E303 too many blank lines (2)
    def relogin_oauth2(self):
    ^
fast_arrow/client.py:164:26: E221 multiple spaces before operator
        self.access_token   = res["access_token"]
                         ^
fast_arrow/client.py:165:27: E221 multiple spaces before operator
        self.refresh_token  = res["refresh_token"]
                          ^
fast_arrow/client.py:166:22: E221 multiple spaces before operator
        self.mfa_code       = res["mfa_code"]
                     ^
fast_arrow/client.py:167:19: E221 multiple spaces before operator
        self.scope          = res["scope"]
                  ^
fast_arrow/client.py:170:5: E303 too many blank lines (2)
    def logout_oauth2(self):
    ^
fast_arrow/client.py:180:16: E711 comparison to None should be 'if cond is None:'
        if res == None:
               ^
fast_arrow/client.py:181:28: E221 multiple spaces before operator
            self.account_id     = None
                           ^
fast_arrow/client.py:182:29: E221 multiple spaces before operator
            self.account_url    = None
                            ^
fast_arrow/client.py:183:30: E221 multiple spaces before operator
            self.access_token   = None
                             ^
fast_arrow/client.py:184:31: E221 multiple spaces before operator
            self.refresh_token  = None
                              ^
fast_arrow/client.py:185:26: E221 multiple spaces before operator
            self.mfa_code       = None
                         ^
fast_arrow/client.py:186:23: E221 multiple spaces before operator
            self.scope          = None
                      ^
fast_arrow/client.py:187:31: E221 multiple spaces before operator
            self.authenticated  = False
                              ^
fast_arrow/exceptions.py:6:1: E302 expected 2 blank lines, found 1
class NotImplementedError(Exception):
^
fast_arrow/exceptions.py:11:1: E302 expected 2 blank lines, found 1
class TradeExecutionError(Exception):
^
fast_arrow/fast_arrow_object.py:6:1: E302 expected 2 blank lines, found 1
class FastArrowObject(dict):
^
fast_arrow/fast_arrow_object.py:14:9: E112 expected an indented block
        requestor = api_requestor.ApiRequestor(
        ^
fast_arrow/fast_arrow_object.py:14:17: E999 IndentationError: expected an indented block
        requestor = api_requestor.ApiRequestor(
                ^
fast_arrow/option_strategies/iron_condor.py:2:1: F401 'pandas as pd' imported but unused
import pandas as pd
^
fast_arrow/option_strategies/iron_condor.py:3:1: F401 'datetime' imported but unused
import datetime
^
fast_arrow/option_strategies/iron_condor.py:11:35: E251 unexpected spaces around keyword / parameter equals
        return sorted(options, key = (lambda x: x['strike_price']))
                                  ^
fast_arrow/option_strategies/iron_condor.py:11:37: E251 unexpected spaces around keyword / parameter equals
        return sorted(options, key = (lambda x: x['strike_price']))
                                    ^
fast_arrow/option_strategies/iron_condor.py:14:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/option_strategies/iron_condor.py:15:80: E501 line too long (81 > 79 characters)
    def gen_leg(cls, option_url, side, position_effect="open", ratio_quantity=1):
                                                                               ^
fast_arrow/option_strategies/iron_condor.py:26:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/option_strategies/iron_condor.py:38:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/option_strategies/iron_condor.py:45:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/option_strategies/iron_condor.py:47:9: E128 continuation line under-indented for visual indent
        width, put_inner_lte_delta, call_inner_lte_delta):
        ^
fast_arrow/option_strategies/iron_condor.py:47:9: E125 continuation line with same indent as next logical line
        width, put_inner_lte_delta, call_inner_lte_delta):
        ^
fast_arrow/option_strategies/iron_condor.py:64:80: E501 line too long (82 > 79 characters)
        put_options_unsorted = list(filter(lambda x: x['type'] == 'put', options))
                                                                               ^
fast_arrow/option_strategies/iron_condor.py:73:80: E501 line too long (87 > 79 characters)
        put_inner_leg = cls.gen_leg(put_options[put_inner_index]["instrument"], "sell")
                                                                               ^
fast_arrow/option_strategies/iron_condor.py:74:80: E501 line too long (86 > 79 characters)
        put_outer_leg = cls.gen_leg(put_options[put_outer_index]["instrument"], "buy")
                                                                               ^
fast_arrow/option_strategies/iron_condor.py:77:9: E303 too many blank lines (2)
        #
        ^
fast_arrow/option_strategies/iron_condor.py:80:80: E501 line too long (84 > 79 characters)
        call_options_unsorted = list(filter(lambda x: x['type'] == 'call', options))
                                                                               ^
fast_arrow/option_strategies/iron_condor.py:88:80: E501 line too long (89 > 79 characters)
        # so np.argmax is able to walk up the index until it finds "call_inner_lte_delta"
                                                                               ^
fast_arrow/option_strategies/iron_condor.py:96:80: E501 line too long (90 > 79 characters)
        call_inner_leg = cls.gen_leg(call_options[call_inner_index]["instrument"], "sell")
                                                                               ^
fast_arrow/option_strategies/iron_condor.py:97:80: E501 line too long (89 > 79 characters)
        call_outer_leg = cls.gen_leg(call_options[call_outer_index]["instrument"], "buy")
                                                                               ^
fast_arrow/option_strategies/iron_condor.py:106:14: E225 missing whitespace around operator
            +Decimal(put_options[put_inner_index]['adjusted_mark_price'])
             ^
fast_arrow/option_strategies/iron_condor.py:107:14: E225 missing whitespace around operator
            +Decimal(call_options[call_inner_index]['adjusted_mark_price'])
             ^
fast_arrow/option_strategies/iron_condor.py:108:14: E225 missing whitespace around operator
            -Decimal(call_options[call_outer_index]['adjusted_mark_price'])
             ^
fast_arrow/option_strategies/iron_condor.py:124:13: E128 continuation line under-indented for visual indent
            "max_bid_ask_spread": max_bid_ask_spread}
            ^
fast_arrow/option_strategies/vertical.py:1:1: F401 'numpy as np' imported but unused
import numpy as np
^
fast_arrow/option_strategies/vertical.py:3:1: F401 'datetime' imported but unused
import datetime
^
fast_arrow/option_strategies/vertical.py:5:1: E302 expected 2 blank lines, found 1
class Vertical(object):
^
fast_arrow/option_strategies/vertical.py:28:80: E501 line too long (88 > 79 characters)
        df['expiration_date'] = pd.to_datetime(df['expiration_date'], format="%Y-%m-%d")
                                                                               ^
fast_arrow/option_strategies/vertical.py:34:14: E231 missing whitespace after ','
        for k,v in df.groupby("expiration_date"):
             ^
fast_arrow/option_strategies/vertical.py:41:80: E501 line too long (83 > 79 characters)
                df.loc[v.index, "margin"] = v["strike_price"] - sdf["strike_price"]
                                                                               ^
fast_arrow/option_strategies/vertical.py:45:80: E501 line too long (96 > 79 characters)
            df.loc[v.index, "premium"] = (v["adjusted_mark_price"] - sdf["adjusted_mark_price"])
                                                                               ^
fast_arrow/resources/__init__.py:1:1: W391 blank line at end of file

^
fast_arrow/resources/option.py:13:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option.py:18:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option.py:67:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option.py:89:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option.py:99:23: E225 missing whitespace around operator
            if len(md)>0:
                      ^
fast_arrow/resources/option.py:102:36: E201 whitespace after '('
                merged_dict = dict( list(o.items()) + list(md.items()) )
                                   ^
fast_arrow/resources/option.py:102:71: E202 whitespace before ')'
                merged_dict = dict( list(o.items()) + list(md.items()) )
                                                                      ^
fast_arrow/resources/option.py:104:36: E201 whitespace after '('
                merged_dict = dict( list(o.items()) )
                                   ^
fast_arrow/resources/option.py:104:52: E202 whitespace before ')'
                merged_dict = dict( list(o.items()) )
                                                   ^
fast_arrow/resources/option_chain.py:15:9: E306 expected 1 blank line before a nested definition, found 0
        def filter_func(x):
        ^
fast_arrow/resources/option_event.py:13:19: E201 whitespace after '{'
        params = { }
                  ^
fast_arrow/resources/option_event.py:22:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_event.py:33:32: E201 whitespace after '('
            merged_dict = dict( list(oe.items()) + list(merge_me.items()) )
                               ^
fast_arrow/resources/option_event.py:33:74: E202 whitespace before ')'
            merged_dict = dict( list(oe.items()) + list(merge_me.items()) )
                                                                         ^
fast_arrow/resources/option_event.py:38:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_event.py:51:26: E711 comparison to None should be 'if cond is None:'
                if oe[k] == None:
                         ^
fast_arrow/resources/option_marketdata.py:11:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_marketdata.py:18:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_marketdata.py:23:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_marketdata.py:33:60: F821 undefined name 'bearer'
                    data = client.get(data["next"], bearer=bearer)
                                                           ^
fast_arrow/resources/option_marketdata.py:39:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_marketdata.py:44:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_marketdata.py:51:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_marketdata.py:56:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_marketdata.py:62:28: E202 whitespace before '}'
            "5year": "week" }
                           ^
fast_arrow/resources/option_marketdata.py:66:80: E501 line too long (81 > 79 characters)
        request_url = "https://api.robinhood.com/marketdata/options/historicals/"
                                                                               ^
fast_arrow/resources/option_marketdata.py:68:23: E201 whitespace after '{'
            params = { "span": span, "interval": interval, "instruments": ",".join(_urls) }
                      ^
fast_arrow/resources/option_marketdata.py:68:80: E501 line too long (91 > 79 characters)
            params = { "span": span, "interval": interval, "instruments": ",".join(_urls) }
                                                                               ^
fast_arrow/resources/option_marketdata.py:68:90: E202 whitespace before '}'
            params = { "span": span, "interval": interval, "instruments": ",".join(_urls) }
                                                                                         ^
fast_arrow/resources/option_order.py:1:1: F401 'fast_arrow.resources.option.Option' imported but unused
from fast_arrow.resources.option import Option
^
fast_arrow/resources/option_order.py:2:1: F401 'fast_arrow.exceptions.NotImplementedError' imported but unused
from fast_arrow.exceptions import NotImplementedError, TradeExecutionError
^
fast_arrow/resources/option_order.py:17:80: E501 line too long (80 > 79 characters)
        max_fetches = kwargs['max_fetches'] if 'max_fetches' in kwargs else None
                                                                               ^
fast_arrow/resources/option_order.py:40:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_order.py:47:26: E711 comparison to None should be 'if cond is None:'
                if oo[k] == None:
                         ^
fast_arrow/resources/option_order.py:54:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_order.py:72:26: E231 missing whitespace after ','
                    for k,v in oo.items():
                         ^
fast_arrow/resources/option_order.py:73:80: E501 line too long (129 > 79 characters)
                        if k not in ['legs', 'price', 'type', 'premium', 'processed_premium', 'response_category', 'cancel_url']:
                                                                               ^
fast_arrow/resources/option_order.py:85:26: E231 missing whitespace after ','
                    for k,v in leg.items():
                         ^
fast_arrow/resources/option_order.py:97:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_order.py:98:80: E501 line too long (120 > 79 characters)
    def submit(cls, client, direction, legs, price, quantity, time_in_force, trigger, order_type, run_validations=True):
                                                                               ^
fast_arrow/resources/option_order.py:152:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_order.py:161:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_position.py:4:1: F401 'fast_arrow.util.chunked_list' imported but unused
from fast_arrow.util import chunked_list, is_max_date_gt
^
fast_arrow/resources/option_position.py:15:80: E501 line too long (80 > 79 characters)
        max_fetches = kwargs['max_fetches'] if 'max_fetches' in kwargs else None
                                                                               ^
fast_arrow/resources/option_position.py:18:19: E201 whitespace after '{'
        params = { }
                  ^
fast_arrow/resources/option_position.py:39:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_position.py:47:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_position.py:60:32: E201 whitespace after '('
            merged_dict = dict( list(op.items()) + list(md.items()) )
                               ^
fast_arrow/resources/option_position.py:60:68: E202 whitespace before ')'
            merged_dict = dict( list(op.items()) + list(md.items()) )
                                                                   ^
fast_arrow/resources/option_position.py:65:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_position.py:73:80: E501 line too long (120 > 79 characters)
            # there is an overlap in keys, {'chain_symbol', 'url', 'type', 'created_at', 'id', 'updated_at', 'chain_id'}
                                                                               ^
fast_arrow/resources/option_position.py:77:80: E501 line too long (85 > 79 characters)
            #   idata_subset = dict((k, idata[k]) for k in wanted_keys if k in idata)
                                                                               ^
fast_arrow/resources/option_position.py:84:32: E201 whitespace after '('
            merged_dict = dict( list(op.items()) + list(merge_me.items()) )
                               ^
fast_arrow/resources/option_position.py:84:74: E202 whitespace before ')'
            merged_dict = dict( list(op.items()) + list(merge_me.items()) )
                                                                         ^
fast_arrow/resources/option_position.py:90:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/option_position.py:105:26: E711 comparison to None should be 'if cond is None:'
                if op[k] == None:
                         ^
fast_arrow/resources/option_position.py:109:80: E501 line too long (124 > 79 characters)
            op["chance_of_profit"] = (op["chance_of_profit_long"] if op["type"] == "long" else op["chance_of_profit_short"])
                                                                               ^
fast_arrow/resources/option_position.py:116:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/portfolio.py:9:28: E202 whitespace before '}'
            "5year": "week" }
                           ^
fast_arrow/resources/portfolio.py:16:19: E201 whitespace after '{'
        params = { "span": span, "interval": interval, "bounds": bounds }
                  ^
fast_arrow/resources/portfolio.py:16:72: E202 whitespace before '}'
        params = { "span": span, "interval": interval, "bounds": bounds }
                                                                       ^
fast_arrow/resources/stock.py:3:1: E302 expected 2 blank lines, found 1
class Stock(object):
^
fast_arrow/resources/stock.py:12:80: E501 line too long (80 > 79 characters)
        url = "https://api.robinhood.com/instruments/?symbol={0}".format(symbol)
                                                                               ^
fast_arrow/resources/stock.py:26:23: E225 missing whitespace around operator
            if len(md)>0:
                      ^
fast_arrow/resources/stock.py:32:36: E201 whitespace after '('
                merged_dict = dict( list(s.items()) + list(md_kv.items()) )
                                   ^
fast_arrow/resources/stock.py:32:74: E202 whitespace before ')'
                merged_dict = dict( list(s.items()) + list(md_kv.items()) )
                                                                         ^
fast_arrow/resources/stock.py:34:36: E201 whitespace after '('
                merged_dict = dict( list(s.items()) )
                                   ^
fast_arrow/resources/stock.py:34:52: E202 whitespace before ')'
                merged_dict = dict( list(s.items()) )
                                                   ^
fast_arrow/resources/stock.py:39:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/stock.py:51:52: F821 undefined name 'bearer'
            data = client.get(data["next"], bearer=bearer)
                                                   ^
fast_arrow/resources/stock_marketdata.py:1:1: F401 'fast_arrow.util.chunked_list' imported but unused
from fast_arrow.util import chunked_list
^
fast_arrow/resources/stock_marketdata.py:37:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/stock_marketdata.py:47:5: E303 too many blank lines (2)
    @classmethod
    ^
fast_arrow/resources/stock_marketdata.py:58:52: F821 undefined name 'bearer'
            data = client.get(data["next"], bearer=bearer)
                                                   ^
tests/test_util.py:5:1: E302 expected 2 blank lines, found 1
def gen_vcr():
^
tests/test_util.py:12:1: E302 expected 2 blank lines, found 1
def gen_client():
^
tests/resources/test_dividend.py:4:1: F401 'unittest' imported but unused
import unittest
^
tests/resources/test_dividend.py:6:1: E302 expected 2 blank lines, found 1
class TestDividend(object):
^
tests/resources/test_dividend.py:15:17: E128 continuation line under-indented for visual indent
                'payable_date', 'instrument', 'rate',
                ^
tests/resources/test_dividend.py:16:17: E128 continuation line under-indented for visual indent
                'record_date', 'position', 'withholding', 'id', 'paid_at']
                ^
tests/resources/test_option_chain.py:3:1: F401 'unittest' imported but unused
import unittest
^
tests/resources/test_position.py:4:1: F401 'unittest' imported but unused
import unittest
^
tests/resources/test_position.py:6:1: E302 expected 2 blank lines, found 1
class TestPosition(object):
^
tests/resources/test_position.py:19:29: E231 missing whitespace after ','
                'updated_at','shares_held_for_buys', 'average_buy_price',
                            ^
tests/resources/test_position.py:20:29: E231 missing whitespace after ','
                'instrument','intraday_quantity', 'shares_held_for_sells',
                            ^
tests/resources/test_stock.py:4:1: F401 'unittest' imported but unused
import unittest
^
tests/resources/test_stock.py:6:1: E302 expected 2 blank lines, found 1
class TestStock(object):
^
tests/resources/test_stock.py:15:17: E128 continuation line under-indented for visual indent
                'market', 'simple_name', 'min_tick_size', 'maintenance_ratio',
                ^
tests/resources/test_stock.py:16:17: E128 continuation line under-indented for visual indent
                'tradability', 'state', 'type', 'tradeable', 'fundamentals',
                ^
tests/resources/test_stock.py:17:17: E128 continuation line under-indented for visual indent
                'quote', 'symbol', 'day_trade_ratio', 'name',
                ^
tests/resources/test_stock.py:18:17: E128 continuation line under-indented for visual indent
                'tradable_chain_id', 'splits', 'url', 'country',
                ^
tests/resources/test_stock.py:19:17: E128 continuation line under-indented for visual indent
                'bloomberg_unique', 'list_date']
                ^
tests/resources/test_stockorder.py:4:1: F401 'unittest' imported but unused
import unittest
^
tests/resources/test_stockorder.py:6:1: E302 expected 2 blank lines, found 1
class TestStockOrder(object):
^
tests/resources/test_stockorder.py:15:17: E128 continuation line under-indented for visual indent
                'fees', 'cancel', 'response_category',
                ^
tests/resources/test_stockorder.py:16:17: E128 continuation line under-indented for visual indent
                'id', 'cumulative_quantity', 'stop_price', 'reject_reason', 'instrument',
                ^
tests/resources/test_stockorder.py:16:80: E501 line too long (89 > 79 characters)
                'id', 'cumulative_quantity', 'stop_price', 'reject_reason', 'instrument',
                                                                               ^
tests/resources/test_stockorder.py:17:17: E128 continuation line under-indented for visual indent
                'state', 'trigger', 'override_dtbp_checks', 'type',
                ^
tests/resources/test_stockorder.py:18:17: E128 continuation line under-indented for visual indent
                'last_transaction_at', 'price', 'executions', 'extended_hours',
                ^
tests/resources/test_stockorder.py:19:17: E128 continuation line under-indented for visual indent
                'account', 'url', 'created_at', 'side', 'override_day_trade_checks', 'position',
                ^
tests/resources/test_stockorder.py:19:80: E501 line too long (96 > 79 characters)
                'account', 'url', 'created_at', 'side', 'override_day_trade_checks', 'position',
                                                                               ^
tests/resources/test_stockorder.py:20:17: E128 continuation line under-indented for visual indent
                'average_price', 'quantity']
                ^
tests/resources/test_user.py:4:1: F401 'unittest' imported but unused
import unittest
^
tests/resources/test_user.py:6:1: E302 expected 2 blank lines, found 1
class TestUser(object):
^
setup.py:1:1: F401 'os' imported but unused
import os
^
setup.py:49:5: E128 continuation line under-indented for visual indent
    version=version_contents['VERSION'],
    ^
setup.py:50:5: E128 continuation line under-indented for visual indent
    description='A simple yet robust API client for Robinhood',
    ^
setup.py:51:5: E128 continuation line under-indented for visual indent
    long_description=long_description,
    ^
setup.py:52:5: E128 continuation line under-indented for visual indent
    long_description_content_type="text/markdown",
    ^
setup.py:53:5: E128 continuation line under-indented for visual indent
    author='Weston Platter',
    ^
setup.py:54:5: E128 continuation line under-indented for visual indent
    author_email='[email protected]',
    ^
setup.py:55:5: E128 continuation line under-indented for visual indent
    url='https://github.com/westonplatter/fast_arrow/',
    ^
setup.py:56:5: E128 continuation line under-indented for visual indent
    license='MIT License',
    ^
setup.py:57:5: E128 continuation line under-indented for visual indent
    python_requires=">=3.5",
    ^
setup.py:58:5: E128 continuation line under-indented for visual indent
    packages=['fast_arrow', 'fast_arrow.resources', 'fast_arrow.option_strategies'],
    ^
setup.py:58:80: E501 line too long (84 > 79 characters)
    packages=['fast_arrow', 'fast_arrow.resources', 'fast_arrow.option_strategies'],
                                                                               ^
setup.py:59:5: E128 continuation line under-indented for visual indent
    package_data={'fast_arrow': ['ssl_certs/certs.pem']},
    ^
setup.py:60:5: E128 continuation line under-indented for visual indent
    install_requires=deps,
    ^
setup.py:61:5: E128 continuation line under-indented for visual indent
    tests_require=test_deps,
    ^
setup.py:62:5: E128 continuation line under-indented for visual indent
    cmdclass={'test': PyTest},
    ^
setup.py:63:5: E128 continuation line under-indented for visual indent
    project_urls={

Examples - jupyter notebook

Create examples of

  • chart of open_interest for TLT, SPY, QQQ, and IWM for a given expiration date.



For example, TLT call options for Aug-10, open_interest vs strike_price,

screen shot 2018-08-04 at 9 51 05 pm

please add stock and option data schema and definitions

What's your feature?
it's hard to know what the data mean

Why are you interested in it being added?

>>> print(spy.keys())
dict_keys(['margin_initial_ratio', 'rhs_tradability', 'id', 'market', 'simple_name', 'min_tick_size', 'maintenance_ratio', 'tradability', 'state', 'type', 'tradeable', 'fundamentals', 'quote', 'symbol', 'day_trade_ratio', 'name', 'tradable_chain_id', 'splits', 'url', 'country', 'bloomberg_unique', 'list_date'])
>>> print(options[0].keys())
dict_keys(['issue_date', 'tradability', 'strike_price', 'state', 'url', 'expiration_date', 'created_at', 'chain_id', 'updated_at', 'rhs_tradability', 'type', 'chain_symbol', 'min_ticks', 'id'])

Calculate option strategies in fa or other lib?

Overall, I use RH to execute Option strategies. I trade spreads, iron condors, and sometimes calendars. Should fast_arrow house strategy composition? Should fast_arrow compose Vertical Call Spreads for me to decide if I want to buy and sell them?

I'm leaning towards no, but want to get feedback.

Here's what a calculating vertical credit/debit spread could look like,

import numpy as np
import pandas as pd
import datetime

class Spread(object):

    def __init__(self, **kwargs):
        self.fn     = kwargs.pop("fn", None)
        self.symbol = kwargs.pop("symbol", None)
        self.kind   = kwargs.pop("kind", None)
        self.width  = kwargs.pop("width", None)
        self.dte    = kwargs.pop("dte", None)
        self.__load_data()


    def __repr__(self):
        return "<Spread symbol={} kind={} width={} dte={}>".format(self.symbol,
            self.kind, self.width, self.dte)


    def __load_data(self):
        fn = "data/{}.json".format(self.symbol.upper())
        if self.fn == "help":
            fn = "../data/{}.json".format(self.symbol.upper())

        self.df = pd.read_json(fn, orient="records")
        self.df['expiration_date'] = pd.to_datetime(self.df['expiration_date'], format="%Y-%m-%d")


    def calc_for(self, dd):
        '''
        Calc spread data

        :params

            kind        - buy or sell
            type        - put or call
            width       - margin to be used, eg, 1.0 is 100.0
            dte         - days to expiration range, eg, [14,45]

        '''
        self.kind = (dd["kind"] if "kind" in dd else self.kind)
        assert self.kind is not None

        self.type = (dd["type"] if "type" in dd else self.type)
        assert self.type is not None

        self.width = (abs(dd["width"]) if "width" in dd else self.width)
        assert self.width is not None

        self.dte = (dd["dte"] if "dte" in dd else self.dte)
        assert self.dte is not None

        # create the resulting/specific df (sdf is in a row on the keyboard)
        self.sdf = self.df.sort_values(["expiration_date", "strike_price"])

        #
        # filter by dte param
        #
        self.dte_min = (datetime.datetime.now() + datetime.timedelta(days=self.dte[0]))
        self.dte_max = (datetime.datetime.now() + datetime.timedelta(days=self.dte[1]))
        self.sdf = self.sdf[ self.df["expiration_date"] >= self.dte_min ]
        self.sdf = self.sdf[ self.df["expiration_date"] <= self.dte_max ]

        self.sdf = self.sdf[self.sdf["type"] == self.type]

        coef = (1 if self.kind == "sell" else -1)

        for k,v in self.sdf.groupby("expiration_date"):

            sps = np.sort(v.strike_price.values)
            shift = self._calc_shift(sps, self.width)

            if shift is None:
                continue

            shift = int(shift) * coef
            shiftdf = v.shift(shift)

            v["strike_price_shifted"] = (shiftdf["strike_price"])

            if self.kind == "sell":
                v["margin"] = (v["strike_price"] - shiftdf["strike_price"])
            else:
                v["margin"] = 0.0

            v["premium"]        = (v["adjusted_mark_price"] - shiftdf["adjusted_mark_price"])
            v["delta_spread"]   = (v["delta"] - shiftdf["delta"])
            v["theta_spread"]   = (v["theta"] - shiftdf["theta"])

            merge_cols = ["strike_price_shifted", "margin", "premium", "delta_spread", "theta_spread"]

            for col in merge_cols:
                self.sdf.loc[v.index, col] = v[col]

        return self.sdf


    def _calc_shift(self, sps, width):
        '''
        calc spread step to achieve desird margin
        @todo clean this up
        '''
        total = len(sps)
        median = int(np.floor(total/2))

        if np.allclose((abs(sps[median] - 0.50) % 1.0), 0.0):
            median += 1

        min_tick = (sps[median] - sps[median-1]) * 100.0
        if (min_tick - self.width) > 0.0:
            return None

        shift = 0
        diff = 1
        searching = True
        marign = 0

        while searching:
            margin = (sps[median] - sps[median-diff]) * 100
            if np.allclose(margin, self.width):
                shift = diff
                searching = False
            diff += 1

        return shift

HTTPError for a particular slice of expiration dates

Hi, I was querying some options data for SPY, and I ran into a strange error involving Option.mergein_marketdata. I've included some code that replicates this error. Basically, it throws a HTTPError when I query options data for a particular combination of expiration dates. In this case, it's ["2019-05-10", "2019-05-17"]. Any idea why this is happening? How can I fix it?

Thanks.

Version of "fast_arrow": 0.3.1
What you did:

from fast_arrow import Client, Stock, OptionChain, Option
symbol = "SPY"
stock = Stock.fetch(client, symbol)
option_chain = OptionChain.fetch(client, stock["id"], symbol)
exp_dates = option_chain["expiration_dates"][slice(7,11,3)]
ops = Option.in_chain(client, option_chain['id'], exp_dates)
ops = Option.mergein_marketdata_list(client, ops) # error occurs here

What you expected to happen: Get the options data

What actually happened:

HTTPError                                 Traceback (most recent call last)
<ipython-input-155-c923376ae3fe> in <module>
      5 exp_dates = option_chain["expiration_dates"][slice(7,11,3)]
      6 ops = Option.in_chain(client, option_chain['id'], exp_dates)
----> 7 ops = Option.mergein_marketdata_list(client, ops)

~\Miniconda3\lib\site-packages\fast_arrow\resources\option.py in mergein_marketdata_list(cls, client, options)
     90     def mergein_marketdata_list(cls, client, options):
     91         ids = [x["id"] for x in options]
---> 92         mds = OptionMarketdata.quotes_by_instrument_ids(client, ids)
     93         mds = [x for x in mds if x]
     94 

~\Miniconda3\lib\site-packages\fast_arrow\resources\option_marketdata.py in quotes_by_instrument_ids(cls, client, ids)
     13         base_url = "https://api.robinhood.com/options/instruments/"
     14         id_urls = ["{}{}/".format(base_url, _id) for _id in ids]
---> 15         return cls.quotes_by_instrument_urls(client, id_urls)
     16 
     17 

~\Miniconda3\lib\site-packages\fast_arrow\resources\option_marketdata.py in quotes_by_instrument_urls(cls, client, urls)
     27             url = "https://api.robinhood.com/marketdata/options/"
     28             params = {"instruments": ",".join(_urls)}
---> 29             data = client.get(url, params=params)
     30             if data and "results" in data:
     31                 partial_results = data["results"]

~\Miniconda3\lib\site-packages\fast_arrow\client.py in get(self, url, params, retry)
     56                 attempts += 1
     57                 if res.status_code in [400]:
---> 58                     raise e
     59                 elif retry and res.status_code in [403]:
     60                     self.relogin_oauth2()

~\Miniconda3\lib\site-packages\fast_arrow\client.py in get(self, url, params, retry)
     51             try:
     52                 res = requests.get(url, headers=headers, params=params, timeout=15, verify=self.certs)
---> 53                 res.raise_for_status()
     54                 return res.json()
     55             except requests.exceptions.RequestException as e:

~\Miniconda3\lib\site-packages\requests\models.py in raise_for_status(self)
    938 
    939         if http_error_msg:
--> 940             raise HTTPError(http_error_msg, response=self)
    941 
    942     def close(self):

HTTPError: 400 Client Error: Bad Request for url: https://api.robinhood.com/marketdata/options/?instruments=https%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F9252c014-91aa-4e4a-ac5b-f3978253b028%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F10380fa4-4598-4690-b844-c6e3e3577599%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F3f54d54f-8327-400c-84fd-7efc2da0290f%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F1ac4f880-1792-4df7-9fd1-ab583f803d5d%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F60f2ecd6-641b-47d1-9988-409f9587b090%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fd4a48477-9584-44ee-971a-ac5a872e5322%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F61447399-6dfc-46a6-8031-47c4c0ff47be%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F524e81ae-218c-43c6-9dba-4b510425c238%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F35162977-211b-4b57-aaa1-68d0eb0cd475%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fc9264f2f-db7b-48f0-9829-8831d556d5e1%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F94d8cc2e-ad43-4ed6-bdd3-413d670aca37%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fef563b2e-7c7f-47ea-b494-37929fbe1b73%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Ffc6a866d-4ea6-431b-8643-22bd45591bee%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F0f7e2c72-f145-4696-a221-568c6673b946%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Ff01bea56-a18b-44c8-8d91-41f3728f7c95%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F208ae270-02ea-416c-a9b4-f54d20059b02%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fb41bc855-545b-4cbc-84d6-9a0c603fa78e%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F5ec21a39-3302-493f-8a68-929a3803d6f2%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fcdac0051-3287-478c-bea2-4f94e61712c1%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F8efb746a-8360-41f7-8275-d0d39b256c15%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fe8e7d6ce-41f4-4b94-8c8f-21efa7a84581%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F6129126a-407f-4132-8c15-9cb88d22e79a%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F1c1844c5-7ef5-46bf-b9a1-46545e8e77da%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F72012f8d-38d9-4552-8d78-075259bdca95%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fc5977ab8-3654-436a-a64d-bde332e5d4a8%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F2f354e7a-63c5-42cc-a9e2-84e7ff411c6b%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F0c1a6cd4-9c62-4024-a374-f335cb84c410%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F3120055c-ae3e-4de0-96cb-942149dad32b%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fa17c9cd9-394e-4b1b-a90f-01e5ff09194d%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F5b0d6c17-6000-432d-9468-416eff21d7f9%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fce4a1130-a936-4c7e-8f14-7f121502e97e%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fb0458a87-9ebc-49a5-9fc9-b1f48c1c0605%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F0311eec6-a134-4393-9b96-bd2532b83b5c%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fce1b8b73-cd7c-4e6c-af7b-014f020d07d2%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F9d1b349f-d7c4-40c0-8e16-06615bdeab56%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fca2ba899-ce6d-41e2-ae5c-788c10593713%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fed55e3de-8608-4f33-8b64-2fd07c606b05%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fbf4a26c0-9938-4954-a463-9f73a4aff86f%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Ff61bd27d-3a9a-4457-be41-90c585e50c60%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fbff80851-3022-4ee3-8b7a-5a2a58e51bb7%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fb6c02b9c-9d47-4af9-95d7-297a2887c656%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Ffb2022d6-778d-4ba6-aa1c-87bcc6334b25%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F21376374-fe1e-4f83-8031-911cdf774870%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F55eeef12-3eb8-4db7-a052-b41f0c0eeb3c%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F8f8ecfa9-0a71-4cdf-b884-16c725178e67%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F077aef4f-9600-4431-827d-8b04d546f141%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F36736135-dc31-4cff-9956-3a78eb0990cd%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F9704b82a-95b2-4d03-8e28-b4ce5a8cc4b0%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2Fe0dc5fd9-1f24-44f0-857a-45543f2043f8%2F%2Chttps%3A%2F%2Fapi.robinhood.com%2Foptions%2Finstruments%2F39914fad-025f-4974-88bf-9a7c1b004eaf%2F

Update urllib3

Please provide some basic details with your issue
Version of "fast_arrow"
What you did
What you expected to happen
What actually happened

Additional relevant information
recevied github security alert. todo ">=1.24.2"

Make an options order

Todos

  • submit a 1 leg option order (eg, buy a OTM $SPY call option)
  • submit a 2 leg option order (eg, sell a OTM $SPY vertical put spread)
  • submit a 4 leg option order (eg, sell a OTM $SPY iron condor)

Login fails

upgraded to latest package today to see if that would fix and still having issues...all was running fine last Friday and today I'm getting a

400 Client Error: Bad Request for url: https://api.robinhood.com/oauth2/token/

log into Fast_Arrow

  2 client = Client(username=XXXXX, password=XXXXXX)

----> 3 client.authenticate()
4 #login_oauth2
5 # client = Client.login_oauth2(self,username=XXXXX, password=XXXXX)
~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\fast_arrow\client.py in authenticate(self)
32 '''
33 if "username" in self.options and "password" in self.options:
---> 34 self.login_oauth2(self.options["username"], self.options["password"], self.options.get('mfa_code'))
35 elif "access_token" in self.options and "refresh_token" in self.options:
36 self.access_token = self.options["access_token"]

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\fast_arrow\client.py in login_oauth2(self, username, password, mfa_code)
117 data['mfa_code'] = mfa_code
118 url = "https://api.robinhood.com/oauth2/token/"
--> 119 res = self.post(url, payload=data, retry=False)
120
121 if res is None:

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\fast_arrow\client.py in post(self, url, payload, retry)
78 attempts += 1
79 if res.status_code in [400]:
---> 80 raise e
81 elif retry and res.status_code in [403]:
82 self.relogin_oauth2()

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\fast_arrow\client.py in post(self, url, payload, retry)
70 try:
71 res = requests.post(url, headers=headers, data=payload, timeout=15, verify=self.certs)
---> 72 res.raise_for_status()
73 if res.headers['Content-Length'] == '0':
74 return None

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\requests\models.py in raise_for_status(self)
938
939 if http_error_msg:
--> 940 raise HTTPError(http_error_msg, response=self)
941
942 def close(self):

Login fails

Everything was working Friday and today was having issues logging in today. Upgraded this morning and still having issues.

1 # log into Fast_Arrow
2 client = Client(username=XXXXX, password=XXXXXX)
----> 3 client.authenticate()
4 #login_oauth2
5 # client = Client.login_oauth2(self,username=XXXXX, password=XXXXX)

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\fast_arrow\client.py in authenticate(self)
32 '''
33 if "username" in self.options and "password" in self.options:
---> 34 self.login_oauth2(self.options["username"], self.options["password"], self.options.get('mfa_code'))
35 elif "access_token" in self.options and "refresh_token" in self.options:
36 self.access_token = self.options["access_token"]

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\fast_arrow\client.py in login_oauth2(self, username, password, mfa_code)
117 data['mfa_code'] = mfa_code
118 url = "https://api.robinhood.com/oauth2/token/"
--> 119 res = self.post(url, payload=data, retry=False)
120
121 if res is None:

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\fast_arrow\client.py in post(self, url, payload, retry)
78 attempts += 1
79 if res.status_code in [400]:
---> 80 raise e
81 elif retry and res.status_code in [403]:
82 self.relogin_oauth2()

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\fast_arrow\client.py in post(self, url, payload, retry)
70 try:
71 res = requests.post(url, headers=headers, data=payload, timeout=15, verify=self.certs)
---> 72 res.raise_for_status()
73 if res.headers['Content-Length'] == '0':
74 return None

~\AppData\Local\Continuum\anaconda3\envs\py3.6\lib\site-packages\requests\models.py in raise_for_status(self)
938
939 if http_error_msg:
--> 940 raise HTTPError(http_error_msg, response=self)
941
942 def close(self):

How to generate auth file?

In the example, it uses "fast_arrow_auth.json", but what information should be put in this file and how do I get it from robinhood? I am not seeing anywhere it gives me an API key. Thank you!

OptionChain.fetch returns 2 symbols for AMZN

Not sure why this happens, but this is the data I'm seeing.

request

params = {
  'equity_instrument_ids': 'c0bb3aec-bd1e-471e-a4f0-ca011cbec711', 
  'state': 'active', 
  'tradability': 'tradable'
}

response

{'previous': None, 'results': [
  {'can_open_position': False, 'symbol': '2AMZN', 'trade_value_multiplier': '100.0000', 'underlying_instruments': [{'instrument': 'https://api.robinhood.com/instruments/c0bb3aec-bd1e-471e-a4f0-ca011cbec711/', 'id': '315c5097-db2d-4a9e-88ee-80ff8737b0df', 'quantity': 100}], 'expiration_dates': [], 'cash_component': None, 'min_ticks': {'cutoff_price': '3.00', 'below_tick': '0.01', 'above_tick': '0.05'}, 'id': '0eb1bdd2-f0c9-494a-ba1d-2dd7659df8c4'}, 
  {'can_open_position': True, 'symbol': 'AMZN', 'trade_value_multiplier': '100.0000', 'underlying_instruments': [{'instrument': 'https://api.robinhood.com/instruments/c0bb3aec-bd1e-471e-a4f0-ca011cbec711/', 'id': '13a08d2e-81ad-4801-aee1-e5bb1ef789b6', 'quantity': 100}], 'expiration_dates': ['2018-08-31', '2018-09-07', '2018-09-14', '2018-09-21', '2018-09-28', '2018-10-05', '2018-10-19', '2018-11-16', '2018-12-21', '2019-01-18', '2019-02-15', '2019-04-18', '2019-06-21', '2020-01-17', '2020-06-19'], 'cash_component': None, 'min_ticks': {'cutoff_price': '3.00', 'below_tick': '0.01', 'above_tick': '0.05'}, 'id': '11226a7c-8bf6-4332-8d62-e423a4f82046'}
], 'next': None}

install, is it just me?

Collecting fast_arrow
Cache entry deserialization failed, entry ignored
Using cached https://files.pythonhosted.org/packages/ad/3c/a18ad138b7e5c29cd63b3811baa1573af74810001933785b222b0faa3886/fast_arrow-0.2.4-py3-none-any.whl
Requirement already satisfied: yarl in /usr/local/lib/python3.6/dist-packages (from fast_arrow)
Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg (from fast_arrow)
Requirement already satisfied: pathlib2 in /usr/local/lib/python3.6/dist-packages (from fast_arrow)
Requirement already satisfied: click in /usr/local/lib/python3.6/dist-packages/click-6.7-py3.6.egg (from fast_arrow)
Requirement already satisfied: idna>=2.0 in /usr/lib/python3/dist-packages (from yarl->fast_arrow)
Requirement already satisfied: multidict>=4.0 in /usr/local/lib/python3.6/dist-packages (from yarl->fast_arrow)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages/certifi-2018.8.13-py3.6.egg (from requests->fast_arrow)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages/chardet-3.0.4-py3.6.egg (from requests->fast_arrow)
Requirement already satisfied: urllib3<1.23,>=1.21.1 in /usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg (from requests->fast_arrow)
Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from pathlib2->fast_arrow)
Installing collected packages: fast-arrow
Successfully installed fast-arrow-0.2.4
root@ip:/home/ubuntu/FAST# python3.6 fast.py
Fatal Python error: Cannot recover from stack overflow.

Current thread 0x00007fe51c9d4740 (most recent call first):
File "/usr/lib/python3.6/threading.py", line 226 in init
File "/usr/lib/python3.6/queue.py", line 39 in init
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/connectionpool.py", line 181 in init
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/connectionpool.py", line 769 in init
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 195 in _new_pool
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 261 in connection_from_pool_key
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 240 in connection_from_context
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 227 in connection_from_host
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 279 in connection_from_url
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/adapters.py", line 309 in get_connection
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/adapters.py", line 405 in send
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/sessions.py", line 618 in send
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/sessions.py", line 508 in request
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/api.py", line 58 in request
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/api.py", line 112 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 75 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
...
Aborted

Current thread 0x00007f6d8a294740 (most recent call first):
File "/usr/lib/python3.6/threading.py", line 226 in init
File "/usr/lib/python3.6/queue.py", line 39 in init
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/connectionpool.py", line 181 in init
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/connectionpool.py", line 769 in init
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 195 in _new_pool
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 261 in connection_from_pool_key
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 240 in connection_from_context
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 227 in connection_from_host
File "/usr/local/lib/python3.6/dist-packages/urllib3-1.22-py3.6.egg/urllib3/poolmanager.py", line 279 in connection_from_url
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/adapters.py", line 309 in get_connection
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/adapters.py", line 405 in send
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/sessions.py", line 618 in send
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/sessions.py", line 508 in request
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/api.py", line 58 in request
File "/usr/local/lib/python3.6/dist-packages/requests-2.18.4-py3.6.egg/requests/api.py", line 112 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 75 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 148 in relogin_oauth2
File "/usr/local/lib/python3.6/dist-packages/fast_arrow/client.py", line 81 in post
...

fetch historical data - Option and Stock

Options

  • fetch by id
  • fetch by id with respect to span and interval.
  • fetch by ids and pair the options (eg, Call Credit Spread on TLT)
  • probably more items as I get into this

Stocks

  • fetch by id
  • fetch by ids
  • customize span and interval

option_order_place_single.py Key Error

I'm sure this is more of something I'm doing wrong but I get an error when I try and run option_order_place_single.py. I have edited the config file with my account information but when I try and run the script I'll get this error

Traceback (most recent call last): File "C:/Users/Marc/fast_arrow/examples/option_order_place_single.py", line 18, in <module> username = config['account']['username'] File "C:\Users\Marc\AppData\Local\Programs\Python\Python36-32\lib\configparser.py", line 959, in __getitem__ raise KeyError(key) KeyError: 'account'

Thanks for looking

Buying option to close

Hi,
Thanks for the great software. I used option_order_place_single.py as the base to sell short an option contract and it works great. However, I'm having trouble buy an option contract to close it.

To sell short, I use

direction = "credit"
legs = [{ "side": "sell",
        "option": candidate["url"],
        "position_effect": "open",
        "ratio_quantity": 1 }]

which works. To buy, I tried

direction = "debit"
legs = [{ "side": "buy",
    "option": data["url"],
    "position_effect": "close",
    "ratio_quantity": 1 }]

I get the url of the option I sold short using OptionPosition.all & OptionPosition.mergein_market_list. Is there any issues that you are aware of in short selling options and buy options to close it?

(epic) Options Position data

Todos:

  • adjust the greeks to be positive/negative based on type (ie, long/short)
  • add Strike Price to resulting position data
  • batch request MarketData like the web ui does (rather than n+1 querying the API).

(epic) basic RH info

The goal is to setup the basic structure for the API client and fetch basic RH account info.

Basic structure:

  • authentication
  • MFA authentication
  • migrate token to oauth2 bearer token
  • basic test suite with a CI

Endpoints to fetch from:

  • get user
  • get positions
  • get option_positions

A little help for the ignorant folks like myself

What's your feature?
Description with example on how to get this code running. I've looked through and tried to use the examples but I can't interpret it effectively.

Why are you interested in it being added?
I am not skilled at programming by any means and barely understand the basics. This looks like it can do quite a bit and I'm very interested in using it.

That said, I have no idea how to utilize these scripts and what variables to fill in, etc, etc.
Could you create some type of basic information "how-to", to get me started.

For example, how to properly use auth.py and then do an option_chain.py.

How does one correctly login? How do I get the information that I need to type in for some of these parameters? option_id, etc? Some basics on this would be greatly appreciated and I'm sure helpful to others who like me, aren't as educated in this as some.

Many thanks!

Fix Requests Error Handling

Version of "fast_arrow:" master
What you did: Made a request with expired/invalid auth tokens
What you expected to happen: A 4xx error from requests or a nice InvalidCredentials error of some sort
What actually happened: The Client.get and Client.post methods absorb the exceptions and return None, causing an error in other parts of the library that process response data.
Additional relevant information:

The Client.get and Client.post methods specifically catch 403 and try to reauthenticate using refresh tokens, but I think I'm seeing 401s instead these days (unrelated: I'm not sure if the refresh tokens are working at all). Either way, for any error status code in 4xx-5xx besides 400 and 429 (for post), or even the second time in a call where the result is 403, the method will silently fail and return None to whatever called it. It is not immediately apparent that a login failure occurred in this case, since the actual error will usually be a NoneType related issue in completely different code.

TL;DR: When there is a requests.exceptions.RequestException that the library cannot recover from, the exception should probably be raised so that calling code can deal with it. That, or create generic exceptions to distinguish between server errors, client errors, and authentication issues.

NameError: name 'get' is not defined

While attempting to use pip-installed fast-arrow 0.2.7 on Python with these lines, I noticed this error

client = Client(username=username, password=password)
orders = StockOrder().all(client)

NameError: name 'get' is not defined

historical_quotes_by_urls

Please provide some basic details with your issue
Version of "fast_arrow"
What you did
What you expected to happen
What actually happened
Additional relevant information

Thank you for sharing. I face up with a problem. The historical_quotes_by_urls function always returns volume of zero.

Implement "updated_at" query param for Stock & Option orders

According to the unofficial docs, it's possible to restrict/scope orders by earliest data. Details here -> https://github.com/sanko/Robinhood/blob/master/Order.md#gather-recent-orders.

Therefore, implement something like this.
curl -v https://api.robinhood.com/orders/?updated_at="2018-09-02T13:24:13.156344Z"
-H "Accept: application/json"
-H "Authorization: Token a9a7007f890c790a30a0e0f0a7a07a0242354114"

Todo:

  • add query param to Option order fetching
  • add query param to Stock order fetching

Create issue template

Version of "fast_arrow"
What you did
What you expected to happen
What actually happened
Additional relevant information

the position data is not real-time?

Please provide some basic details with your issue
Version of "fast_arrow"
What you did
What you expected to happen
What actually happened
Additional relevant information
Hello. When I use OptionPosition.all(client), the data seems not to be real-time.

Option chain response does not include requested ticker.

The following code, intended to get an option chain for 'ROKU' returns an error as shown below:

from fast_arrow import Stock, OptionChain, Option, OptionOrder
from fast_arrow_auth import Client

client = Client(username='username', password='password')
symb = 'ROKU'
stock = Stock.fetch(client, symb)
stockid = stock['id']

everything is fine until this point

chain = OptionChain.fetch(client, stockid, symb)

----------- Error Message --------------
Traceback (most recent call last):
File "", line 1, in
File "C:\path\fast_arrow\resources\option_chain.py", line 19, in fetch
return results[0]
IndexError: list index out of range


If I go into the function and look for the url request portion of the code..the response returns 750 ticker chains but does not include 'ROKU'. It seems to be returning only a portion of the available option chains. Also, the parameters for OptionChain.fetch() do not seem to 'pre-filter' the response at all...so if this is an avenue for troubleshooting this problem I can try adding new parameters to the request.

Is there are a possible fix for this? Thanks.

please add example stock quote

What's your feature?
please add example for stock quote
Why are you interested in it being added?
options prices depend on underlying price but there is no example of how to read underlying price

Fetch options trading history

Goal - fetch all data required to create a P/L for a single symbol. It's really a unified event stream for a given symbol.

simple_metrics will take care of interpreting or presenting the data. fast_arrow merely needs to fetch the raw data. For example, fa shouldn't worry about comparing past option trades with current option positions to determine if those positions are still open.

Required data,

cannot import name 'client' from 'fast_arrow'

I am getting error cannot import name 'client' from 'fast_arrow'. All i did was tried to import it with from fast_arrow import client . I am using Windows 10 Home, 64 bit, python 3.7.1, fast-arrow==0.0.3. Please kindly advise.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.