def __init__(self): self._future_date = date.today() + timedelta(5) self._rh = Robinhood() self._rh.login(username=USERNAME, password=PASSWORD, qr_code=MFA)
def __init__(self, name: str = 'pyrh_adapter'): super().__init__(name, ['pyrh_request', 'trade']) self.rbn = Robinhood() self.logged_in = False self.client_req = Queue() self.requests = Queue() self.request_lock = Lock()
def get_paginated_results( client: Robinhood, url: str, **kwargs: Any) -> Generator[Dict[str, Any], None, None]: page = client.get(url, **kwargs) yield from page['results'] while page['next']: page = client.get(page['next']) yield from page['results']
def __init__(self, username, pwd, rsi=5): self.rh = Robinhood() self.rh.login(username=username, password=pwd) self.rsiPeriod = rsi self.enteredPosition = False self.s = sched.scheduler(time.time, time.sleep) self.data = np.array([]) self.closePrices = []
def rh_setup(): load_dotenv(verbose=True) rh_user = os.getenv("ROBINHOOD_USERNAME") rh_pass = os.getenv("ROBINHOOD_PASSWORD") rh_qr = os.getenv("ROBINHOOD_QR") rh = Robinhood() rh.login(username=rh_user, password=rh_pass, qr_code=rh_qr) return rh
def test_bad_logout(): """logout without logging in""" if not LOGIN_OK: pytest.xfail("cannot test without valid user/passwd") rh_obj = Robinhood() with pytest.warns(UserWarning): req = rh_obj.logout() assert req.status_code != 200
def login(): load_dotenv() try: rh = load_session() except InvalidCacheFile: rh = Robinhood(username=os.getenv("username"), password=os.getenv("password")) rh.login() dump_session(rh) # so you don't have to do mfa again return rh
def login(email: str, password: str, mfa_secret: str) -> Robinhood: client = Robinhood(email, password) totp = pyotp.TOTP(mfa_secret) # We do this, because we don't want to modify the underlying API library # excessively to support this. Therefore, we monkey-patch our way to # success. with mock_stdin(totp.now()): client.login() return client
def test_intstruments(config=CONFIG): """test `instruments` endpoint""" # TODO: this test is bad, just repeat of code inside endpoint params = {"query": CONFIG.get("FETCH", "test_ticker")} headers = {"User-Agent": CONFIG.get("FETCH", "user_agent")} address = Robinhood().endpoints["instruments"] res = requests.get(address, headers=headers, params=params) res.raise_for_status() hard_data = res.json()["results"] data = Robinhood().instruments(CONFIG.get("FETCH", "test_ticker")) assert data == hard_data
def test_logout(config=CONFIG): """make sure logout works""" if not LOGIN_OK: pytest.xfail("cannot test without valid user/passwd") rh_obj = Robinhood() assert rh_obj.login( username=config.get("LOGIN", "username"), password=config.get("LOGIN", "password"), ) assert rh_obj.auth_token is not None req = rh_obj.logout() assert req.status_code == 200
def __init__(self, logger: logging.Logger): """Authenticates Robinhood object and gathers the portfolio information to store it in a variable. Args: logger: Takes the class ``logging.Logger`` as an argument. """ rh = Robinhood() rh.login(username=env.robinhood_user, password=env.robinhood_pass, qr_code=env.robinhood_qr) raw_result = rh.positions() self.logger = logger self.result = raw_result['results'] self.rh = rh
def create_robinhood_instance(username=None, password=None): try: if not username: username = os.getenv("USERNAME") if not password: password = os.getenv("PASSWORD") rh = Robinhood() rh.login(username, password) return rh except Exception: logger.error("Failed to login, exiting...") sys.exit()
def test_get_news(config=CONFIG): """test `get_news` endpoint""" test_ticker = CONFIG.get("FETCH", "test_ticker") raw_news = helpers.fetch_REST_directly("news", test_ticker, config) get_news = Robinhood().get_news(test_ticker) assert get_news == raw_news
def test_login_badpass(config=CONFIG): """try to login with bad creds""" if not LOGIN_OK: pytest.xfail("cannot test without valid user/passwd") bad_pass = "******" with pytest.raises(RH_exception.LoginFailed): Robinhood().login(username=config.get("LOGIN", "username"), password=bad_pass)
def robinhood() -> None: """Gets investment details from robinhood API.""" if not all([env.robinhood_user, env.robinhood_pass, env.robinhood_qr]): logger.warning("Robinhood username, password or QR code not found.") support.no_env_vars() return sys.stdout.write("\rGetting your investment details.") rh = Robinhood() rh.login(username=env.robinhood_user, password=env.robinhood_pass, qr_code=env.robinhood_qr) raw_result = rh.positions() result = raw_result["results"] stock_value = watcher(rh, result) speaker.speak(text=stock_value)
def main(self, stock, action, quantity): username = "" password = "" rh = Robinhood() rh.login(username=username, password=password) instrument = rh.instruments(stock)[0] if (action == "buy"): rh.place_buy_order(instrument, quantity) self.enteredTrade = True if (action == "sell"): rh.place_sell_order(instrument, quantity) self.enteredTrade = False
def test_get_historical_data(config=CONFIG): headers = {"User-Agent": CONFIG.get("FETCH", "user_agent")} address = Robinhood().endpoints["historicals"] res = requests.get( address, headers=headers, params={ "symbols": ",".join([CONFIG.get("FETCH", "test_ticker")]).upper(), "interval": "day", "span": "year", "bounds": "regular", }, ) hard_data = res.json()["results"] data = Robinhood().get_historical_quotes( [CONFIG.get("FETCH", "test_ticker")], "day", "year") assert data == hard_data
def addRobinhood(self): rh = Robinhood() if self.RobinHoodUser: rh.login(username=self.RobinHoodUser, password=self.RobinHoodPassword) rh.print_quote("AAPL") else: print("You must set your Robinhood passwords up in init")
def rh_pull_orders_history(user_id, passwd): pyrh_rb = Robinhood() pyrh_rb.login(username=user_id, password=passwd, challenge_type="sms") past_orders = RhWrapper.rh_pull_all_history_orders(pyrh_rb) # keep past orders in reverse chronological order past_orders_sorted = sorted(past_orders, key=itemgetter('last_transaction_at'), reverse=True) orders_saved_to_db = 0 for order in past_orders_sorted: # check if order already in db if order['state'] == 'filled': obj = robinhood_stock_order_history.objects.filter(timestamp=dateutil.parser.parse(order['last_transaction_at'])) if not obj: obj = robinhood_stock_order_history() obj.order_type = order['side'] obj.price = order['average_price'] obj.shares = order['cumulative_quantity'] obj.symbol, name = RhWrapper.rh_pull_symbol_from_instrument_url(order['instrument']) obj.state = order['state'] obj.timestamp = dateutil.parser.parse(order['last_transaction_at']) obj.save() orders_saved_to_db = orders_saved_to_db + 1 else: continue logging.error('orders_saved_to_db: ' + str(orders_saved_to_db))
def get(self, request): #return HttpResponse(request.user.id) #env = environ.Env(DEBUG=(bool, False)) # reading .env file #environ.Env.read_env() currentUser = Account.objects.get(user=request.user) my_trader = Robinhood() my_trader.login(username=currentUser.rhoodID, password=currentUser.rhoodPWD, qr_code=currentUser.rhQ) data = my_trader.portfolios() my_trader.logout() return HttpResponse(data) context = {} return render(request, self.template_name, context)
def test_cancel_bad_order_id(): """cancel a naughty order id""" bad_id = "1234Dx" if not LOGIN_OK: pytest.xfail("cannot test without valid user/passwd") rh_obj = Robinhood() rh_obj.login( username=CONFIG.get("LOGIN", "username"), password=CONFIG.get("LOGIN", "password"), ) with pytest.raises(ValueError): rh_obj.cancel_order(bad_id)
def test_login_happypath(config=CONFIG): """try to log in to robinhood""" global LOGIN_OK if (not config.get("LOGIN", "username")) or (not config.get("LOGIN", "password")): LOGIN_OK = False pytest.xfail("no login credentials given") try: LOGIN_OK = Robinhood().login( username=config.get("LOGIN", "username"), password=config.get("LOGIN", "password"), ) except Exception as err_msg: LOGIN_OK = False raise err_msg assert LOGIN_OK
class TestURLWrapper: """make sure get_url returns expected behavior""" base_url = "https://api.robinhood.com/" rh_obj = Robinhood() def test_url_endpoint(self): """fetch url directly""" global TEST_URL_RESULT req = requests.get(self.base_url) req.raise_for_status() TEST_URL_RESULT = req.json() def test_get_url(self): """fetch url with get_url""" data = self.rh_obj.get_url(self.base_url) assert data == TEST_URL_RESULT
def fetch_REST_directly(endpoint_name, arg_string, config): """fetch REST endpoint (instead of ?arg1=val1&arg2=val2) Args: endpoint_name (str): endpoint name in RH class arg_string (str): additional args to pass onto endpoint config (:obj:`configparser.ConfigParser`, optional): config for args Returns: (:obj:`dict`) JSON-parsed data from Robinhood endpoint """ rh_object = Robinhood() address = rh_object.endpoints[endpoint_name] address = address + arg_string + "/" headers = {"User-Agent": config.get("FETCH", "user_agent")} req = requests.get(address, headers=headers) req.raise_for_status() return req.json()
def login(username=False, password=False, device_token=False, force=False): global my_trader if not username: username = config.get('user') password = config.get('password') device_token = config.get('token') if not password: password = getpass.getpass() try: my_trader = Robinhood(username=username, password=password, device_token=device_token) print(my_trader) except Exception as ex: raise ex print("Password incorrect. Please try again") login(username, force)
class TestFundamentalsHelpers: """wrapper to test fundamental architecture in order""" test_ticker = CONFIG.get("FETCH", "test_ticker") fake_ticker = CONFIG.get("FETCH", "fake_ticker") rh_obj = Robinhood() def test_fundamental_endpoint(self, config=CONFIG): """get raw data from Robinhood to test against""" global TEST_FUNDAMENTAL TEST_FUNDAMENTAL = helpers.fetch_REST_directly("fundamentals", self.test_ticker, config) TEST_FUNDAMENTAL["volume"] = "OVERWRITE" # flaky value @flaky def test_validate_fundamental(self): """validate fetcher""" data = self.rh_obj.get_fundamentals(self.test_ticker) data["volume"] = "OVERWRITE" # flaky value assert data == TEST_FUNDAMENTAL def test_validate_fail_fundamental(self): """validate bad-path exception""" with pytest.raises(NameError): data = self.rh_obj.get_fundamentals(self.fake_ticker) @flaky def test_validate_fundamental_wrapper(self): main_data = self.rh_obj.fundamentals(self.test_ticker) wrapped_data = self.rh_obj.fundamentals(self.test_ticker) main_data["volume"] = "OVERWRITE" # flaky value wrapped_data["volume"] = "OVERWRITE" # flaky value assert wrapped_data == main_data assert wrapped_data == TEST_FUNDAMENTAL
class RobinhoodHelper: def __init__(self): self._future_date = date.today() + timedelta(5) self._rh = Robinhood() self._rh.login(username=USERNAME, password=PASSWORD, qr_code=MFA) def fetch_news(self, stock): stock_to_search = stock clean_stock_list = [] if(self.is_time_to_reauthenticate(date.today())): self._rh.login(username=USERNAME, password=PASSWORD, qr_code=MFA) try: news = self._rh.get_news(stock_to_search) info_results = news["results"] for i in info_results: stock_price = self.format_decimal_price(stock) stock_info = StockInfo(i["uuid"], i["title"], i["source"], i["published_at"], i["preview_text"].replace("\n\n", ""), i["url"], stock_to_search, stock_price) clean_stock_list.append(stock_info) print(stock_to_search + " = " + str(clean_stock_list[0])) except Exception as e: print("Error: ", e, "Occurred.") print("Skipping...") print() return clean_stock_list def is_time_to_reauthenticate(self, now): if(now == self._future_date): self._future_date = date.today() + timedelta(5) return True return False def format_decimal_price(self, stock): TWOPLACES = decimal.Decimal(10) ** -2 price = str(self._rh.last_trade_price(stock)[0][0]) return str(decimal.Decimal(price).quantize(TWOPLACES))
def __init__(self, credentials: str) -> None: self._ext_equity = 0.0 # Set up connection to Robinhood's API. self._rh = Robinhood() self._rh.login(**read_credentials(credentials))
class TheHood: """ A wrapper for producing the kinds of transactions and calls on my Robinhood portfolio I'm looking for. """ def __init__(self, credentials: str) -> None: self._ext_equity = 0.0 # Set up connection to Robinhood's API. self._rh = Robinhood() self._rh.login(**read_credentials(credentials)) @property def extended_hours_equity(self) -> float: """ Keep track of the extended equity and prevent its setting to NoneType. Returns: The current extended equity. """ return self._ext_equity @extended_hours_equity.setter def extended_hours_equity(self, new_equity: Union[float, None]) -> None: """ Keep track of the extended equity and prevent its setting to NoneType. Returns: The current extended equity. """ if type(new_equity) is not float: pass else: self._ext_equity = new_equity @retry def total_dollar_equity(self) -> Tuple[float, float, float]: """ Get values that explain the current monetary value of my account. Returns: A tuple containing today's closing equity in my account, followed by the previous day's closing value and the current extended / after-hours value. """ self.extended_hours_equity = self._rh.extended_hours_equity() return self._rh.equity(), self._rh.equity_previous_close( ), self.extended_hours_equity @retry def account_potential(self) -> float: """ Get the total account potential for comparison against the total account value. I define account potential as the sum of all stocks' current worth plus the absolute value of any losses. Returns: A float representing the account potential. """ stocks = self._rh.securities_owned()['results'] potential_sum = float(self._rh.portfolios()['withdrawable_amount']) for stock in stocks: # Make quantity a float as the API may change when I buy fractional shares. quantity = float(stock['quantity']) buy_price = float(stock['average_buy_price']) potential_sum += quantity * buy_price return potential_sum @retry def dividend_payments(self, since: str = '') -> float: """ If there are dividend payments, I want to graph a sum in Grafana. Args: since: the date since we should allow the summation of dividends. For instance, you may wish to set this to the past year. Returns: A float representing the sum of dividend payments to my account. """ dividends: Dict = self._rh.dividends()['results'] dividend_sum = 0.0 for dividend in dividends: if dividend['state'] == 'paid': if since and not (datetime.fromisoformat( dividend['paid_at'][:-1]) > datetime.fromisoformat(since)): continue dividend_sum += float(dividend['amount']) return dividend_sum
It then compares the price of the stock at a given moment with the initial bought value If it's lower than some threshold, it will automatically sell """ import sys, time sys.path.append('./pyrh') from pyrh import Robinhood from dotenv import load_dotenv load_dotenv() import os USERNAME = os.getenv("RH_USERNAME") PASSWORD = os.getenv("RH_PASSWORD") rh = Robinhood(username=USERNAME, password=PASSWORD) rh.login() # Set how much you're willing to loss PRICE_DIFF_LIMIT = -100 # How many seconds to wait before polling REFRESH_TIME = 1800 def fetch_json_by_url(rh, url): return rh.session.get(url).json() def get_current_positions(rh): positions = rh.positions()