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 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 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_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
class RobinhoodRepository: def __init__(self): self.robinhood_trader = Robinhood() self.robinhood_trader.login(username=credentials.get("robinhoodUsr"), password=credentials.get("robinhoodPwd")) def getStockQuote(self, ticker): quote = self.robinhood_trader.get_quote(ticker) return quote def getPortfolioValue(self): portfolioValue = self.robinhood_trader.portfolios() return portfolioValue def getPortfolio(self): print "fetching portfolio!" portfolio = self.robinhood_trader.securities_owned()["results"] returnPortfolio = [] for position in portfolio: name = self.robinhood_trader.instrument_name_by_url( position["instrument"]) position["name"] = name returnPortfolio.append(position) return returnPortfolio def buyStock(self, ticker): # Note: Sometimes more than one instrument may be returned for a given stock symbol stock_instrument = self.robinhood_trader.instruments(ticker)[0] buy_order = self.robinhood_trader.place_buy_order(stock_instrument, 1) print buy_order
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_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 __init__(self, bot): self.bot = bot global ENDPOINTS with open(endpoints_path) as file: data = file.read() ENDPOINTS = json.loads(data) self.bot.add_cog(Webull(self.bot, self, ENDPOINTS, ENVIRONMENT)) self.bot.add_cog(Robinhood(self.bot, self, ENDPOINTS, ENVIRONMENT))
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 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 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()
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
#Import class from the other file from bot import telegram_chatbot from datetime import datetime from budgettracker import BudgetTracker from robinhood import Robinhood update_id = None #Instantiate objects - telegram_chatbot and BudgetTracker bot = telegram_chatbot('config.cfg') tracker = BudgetTracker() robinhood = Robinhood() def make_reply(msg): try: if msg is not None: #Splits message into list of items output = msg.split(', ') #Get the command (1st item in the comma-separated list) command = output[0] #Get the arguments (if any) (subsequent items in the comma-separated list) if len(output) > 1: args = output[1:] else: args = None #Returns help text if command == 'Help':
from robinhood import Robinhood import yaml stream = open("../credentials/credentials.yml", "r") credentials = yaml.load(stream) # Setup my_trader = Robinhood(); # login my_trader.login(username=credentials.get("robinhoodUsr"), password=credentials.get("robinhoodPwd")) # Get stock information # Note: Sometimes more than one instrument may be returned for a given stock symbol stock_instrument = my_trader.instruments("AMD")[0] # print(stock_instrument) # Get a stock's quote my_trader.print_quote("AMD") # Prompt for a symbol # my_trader.print_quote(); # Print multiple symbols my_trader.print_quotes(stocks=["BBRY", "FB", "MSFT"]) # View all data for a given stock ie. Ask price and size, bid price and size, previous close, adjusted previous close, etc. # quote_info = my_trader.quote_data("GEVO") # print(quote_info); # Place a buy order (uses market bid price) # buy_order = my_trader.place_buy_order(stock_instrument, 1)
totalVolatility = spyVolatility + tltVolatility spyRawAllocation = 1 - (spyVolatility / totalVolatility) spyAllocation = 1 / (1 + math.exp(-20 * (spyRawAllocation - .5))) if spyAllocation > 1: spyAllocation = 1 if spyAllocation < 0: spyAllocation = 0 return spyAllocation success = True rh = Robinhood() success = rh.marketOpenCheck() if not success: print('markets are closed') else: print('markets are open') if success: success = rh.login(username=config.rhuser, password=config.rhpass) if success: print('login succesful') else: print('login unsuccesful') if success:
import csv from robinhood import Robinhood from orderreader import OrderReader rb = Robinhood() rb.login(username="******", password="******") order_reader = OrderReader() order_reader.init_robinhood_from_client(rb) orders = order_reader.get_orders() keys = ['side', 'symbol', 'shares', 'price', 'date', 'state'] with open('orders.csv', 'w') as output_file: dict_writer = csv.DictWriter(output_file, keys) dict_writer.writeheader() dict_writer.writerows(orders)
from robinhood import Robinhood from orderledger import OrderLedger from orderreader import OrderReader def print_pnl(pnls): ''' ''' print('-----------------------------------') print(pnls) rb = Robinhood() rb.login(username="******", password="******") order_reader = OrderReader() order_reader.init_firstrade('firstrade.csv') #order_reader.init_robinhood_from_client(rb) #order_reader.init_robinhood_from_csv('orders.csv') ol = OrderLedger(order_reader.get_orders()) print("last year") ol.get_last_year_pnl() print("current year") ol.get_current_year_pnl() print("unrealized") ol.get_unrealized_pnl(rb) print("positions") ol.show_positions()
def main(): from robinhood import Robinhood # Setup my_trader = Robinhood(); # Login #my_trader.login(username="******", password="******") my_trader.login() # Get stock information # Note: Sometimes more than one instrument may be returned for a # given stock symbol stock_instrument = my_trader.instruments("GEVO")[0] # Get a stock's quote my_trader.print_quote("AAPL") # Prompt for a symbol my_trader.print_quote() # Print multiple symbols my_trader.print_quotes(stocks=["BBRY", "FB", "MSFT"]) # View all data for a given stock ie. Ask price and size, bid price and size, # previous close, adjusted previous close, etc. quote_info = my_trader.quote_data("GEVO") print(quote_info) # View my account print(my_trader.portfolios())
def run_gather_data(): #code that gets and logs performance data print("Gathering Data") success = True rh = Robinhood() now = datetime.datetime.utcnow() try: success = rh.marketOpenCheck() if not success: print('markets are closed') else: print('markets are open') except Exception as e: success = False print('rh market check error ', str(e)) send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("rh market check error. Unexpected error: " + str(e))) if success: try: success = rh.login(username=rhuser, password=rhpass) if success: print('robinhood login succesful') else: print('robinhood login unsuccesful') except Exception as e: success = False print('rh login error ', str(e)) send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("rh login error. Unexpected error: " + str(e))) if success: try: client = MongoClient(mongodb_uri) db = client.get_database() except Exception as e: print('mongo login error ', str(e)) success = False send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("mongo login error. Unexpected error: " + str(e))) if success: try: #get pricing data spyAskPrice = rh.ask_price('SPY') spyBidPrice = rh.bid_price('SPY') spyAvgCost = (spyAskPrice + spyBidPrice) / 2 print('spyAvgCost = ', spyAvgCost) tltAskPrice = rh.ask_price('TLT') tltBidPrice = rh.bid_price('TLT') tltAvgCost = (tltAskPrice + tltBidPrice) / 2 print('tltAvgCost = ', tltAvgCost) except Exception as e: print('etf price error ', str(e)) success = False send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("etf price error. Unexpected error: " + str(e))) if success: try: #get portfolioValue portfolioValue = rh.equity() tltPosition = 0 spyPosition = 0 print('portfolioValue =', portfolioValue) openPositions = rh.securities_owned()['results'] for position in openPositions: instrumentURL = position['instrument'] positionTicker = rh.get_url(instrumentURL)['symbol'] positionQuantity = float(position['quantity']) if (positionTicker == 'SPY'): spyPosition = positionQuantity if (positionTicker == 'TLT'): tltPosition = positionQuantity print('spyPosition = ', spyPosition) print('tltPosition = ', tltPosition) except Exception as e: print('portfolio value error ', str(e)) success = False send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("portfolio value error. Unexpected error: " + str(e))) if success: try: #get treasury risk free rate quandl.ApiConfig.api_key = quandl_key riskFree = (quandl.get("USTREASURY/BILLRATES.3", rows=1, returns='numpy')[0])[1] print('riskFree =', riskFree) except Exception as e: print('risk free error ', str(e)) success = False send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("risk free error. Unexpected error: " + str(e))) if success: try: #get last data lastData = db.rawPrices.find_one(sort=[("timestamp", -1)]) lastTimestamp = lastData['timestamp'] lastSpy = lastData['spy'] lastTlt = lastData['tlt'] lastPortfolio = lastData['portfolio'] lastRiskFree = lastData['annualized90day'] except Exception as e: print('error getting previous data ', str(e)) success = False send_email( mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("error getting previous data. Unexpected error: " + str(e))) if success: try: # save data rawData = { "timestamp": now, "spy": spyAvgCost, "tlt": tltAvgCost, "portfolio": portfolioValue, "annualized90day": riskFree } data_id = db.rawPrices.insert_one(rawData).inserted_id print("data saved to", data_id) except Exception as e: print('data save error ', str(e)) success = False send_email( mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("error calculating change. Unexpected error: " + str(e))) if success: try: # calculate percentage changes spyChange = (spyAvgCost - lastSpy) / lastSpy print('spyChange = ', spyChange) tltChange = (tltAvgCost - lastTlt) / lastTlt print('tltChange = ', tltChange) portfolioChange = (portfolioValue - lastPortfolio) / lastPortfolio print('portfolioChange = ', portfolioChange) elapsedTime = now - lastTimestamp year = datetime.timedelta(days=365) treasuryChange = ((1 + (((lastRiskFree + riskFree) / 2)) / 100) **(divtd(elapsedTime, year))) - 1 print('treasuryChange = ', treasuryChange) except Exception as e: print('error calculating change ', str(e)) success = False send_email( mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("error calculating change. Unexpected error: " + str(e))) if success: try: # save data percentageData = { "timestamp": now, "spy": spyChange, "tlt": tltChange, "portfolio": portfolioChange, "90dayTreasury": treasuryChange } data_id = db.percentageMove.insert_one(percentageData).inserted_id print("data saved to", data_id) except Exception as e: print('data save error ', str(e)) success = False send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("data save error. Unexpected error: " + str(e))) if success: try: # calculate tracking spyTarget = calcAlloc(rh) print('spyTarget = ', spyTarget) tltTarget = 1 - spyTarget print('tltTarget = ', tltTarget) spyActual = (spyPosition * spyAvgCost) / portfolioValue tltActual = (tltPosition * tltAvgCost) / portfolioValue print('spyActual = ', spyActual) print('tltActual = ', tltActual) except Exception as e: print('error calculating tracking ', str(e)) success = False send_email( mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("error calculating tracking. Unexpected error: " + str(e))) if success: try: # save tracking data trackingData = { "timestamp": now, "spyActual": spyActual, "tltActual": tltActual, "spyTarget": spyTarget, "tltTarget": tltTarget } data_id = db.tracking.insert_one(trackingData).inserted_id print("data saved to", data_id) except Exception as e: print('tracking data save error ', str(e)) success = False send_email( mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader data gather error ' + str(datetime.datetime.now())), ("tracking data save error. Unexpected error: " + str(e)))
def __init__(self): self.robinhood_trader = Robinhood() self.robinhood_trader.login(username=credentials.get("robinhoodUsr"), password=credentials.get("robinhoodPwd"))
class TestPortfolioMethods: """test wrappers on `portfolio` endpoint NOTE: reliant on an active account to pull data from """ rh_obj = Robinhood() try: rh_obj.login( username=CONFIG.get('LOGIN', 'username'), #NOTE: py.test fails w/o password password=CONFIG.get('LOGIN', 'password')) except Exception: pass def test_portfolios(self): """check `portfolio` method""" global TEST_PORTFOLIO if not LOGIN_OK: print('Unable to test Portfolio without auth') pytest.xfail('cannot test without valid user/passwd') print(self.rh_obj.auth_token) data = self.rh_obj.portfolios() #TODO validate data TEST_PORTFOLIO = data def test_validate_adjusted_equity(self): """test `adjusted_equity_previous_close` method""" value = self.rh_obj.adjusted_equity_previous_close() assert isinstance(value, float) assert format( value, '.4f') == TEST_PORTFOLIO['adjusted_equity_previous_close'] def test_validate_equity(self): """test `equity` method""" value = self.rh_obj.equity() assert isinstance(value, float) assert format(value, '.4f') == TEST_PORTFOLIO['equity'] def test_equity_previous_close(self): """test `equity_previous_close` method""" value = self.rh_obj.equity_previous_close() assert isinstance(value, float) assert format(value, '.4f') == TEST_PORTFOLIO['equity_previous_close'] def test_excess_margin(self): """test `excess_margin` method""" value = self.rh_obj.excess_margin() assert isinstance(value, float) assert format(value, '.4f') == TEST_PORTFOLIO['excess_margin'] def test_ex_hours_equity(self): """test `extended_hours_equity method""" value = self.rh_obj.extended_hours_equity() assert isinstance(value, float) or (value is None) if value: assert format(value, '.4f') == TEST_PORTFOLIO['extended_hours_equity'] def test_ex_hours_market_value(self): """test `extended_hours_market_value` method""" value = self.rh_obj.extended_hours_market_value() assert isinstance(value, float) or (value is None) if value: assert format( value, '.4f') == TEST_PORTFOLIO['extended_hours_market_value'] def test_last_core_equity(self): """test `last_core_equity` method""" value = self.rh_obj.last_core_equity() assert isinstance(value, float) assert format(value, '.4f') == TEST_PORTFOLIO['last_core_equity'] def test_last_core_market_value(self): """test `last_core_market_value` method""" value = self.rh_obj.last_core_market_value() assert isinstance(value, float) assert format(value, '.4f') == TEST_PORTFOLIO['last_core_market_value'] def test_market_value(self): """test `market_value` method""" value = self.rh_obj.market_value() assert isinstance(value, float) assert format(value, '.4f') == TEST_PORTFOLIO['market_value'] def test_investment_profile(self): """test `investment_profile` endpoint""" data = self.rh_obj.investment_profile() #TODO: validate keys def test_get_account(self): """test `get_account` endpoing""" data = self.rh_obj.get_account()
def main(): from robinhood import Robinhood # Setup my_trader = Robinhood() # Login #my_trader.login(username="******", password="******") my_trader.login() # Get stock information # Note: Sometimes more than one instrument may be returned for a # given stock symbol stock_instrument = my_trader.instruments("GEVO")[0] # Get a stock's quote my_trader.print_quote("AAPL") # Prompt for a symbol my_trader.print_quote() # Print multiple symbols my_trader.print_quotes(stocks=["BBRY", "FB", "MSFT"]) # View all data for a given stock ie. Ask price and size, bid price and size, # previous close, adjusted previous close, etc. quote_info = my_trader.quote_data("GEVO") print(quote_info) # View my account print(my_trader.portfolios())
"symbol": symbol, "date": order["last_transaction_at"], "state": order["state"], } def get_all_history_orders(rb_client): orders = [] past_orders = rb_client.order_history() orders.extend(past_orders["results"]) while past_orders["next"]: print("{} order fetched".format(len(orders))) next_url = past_orders["next"] past_orders = fetch_json_by_url(rb_client, next_url) orders.extend(past_orders["results"]) print("{} order fetched".format(len(orders))) return orders rb = Robinhood() # !!!!!! change the username and passs, be careful when paste the code to public rb.login(username="******", password="******") past_orders = get_all_history_orders(rb) instruments_db = shelve.open("instruments.db") orders = [order_item_info(order, rb, instruments_db) for order in past_orders] keys = ["side", "symbol", "shares", "price", "date", "state"] with open("orders.csv", "w") as output_file: dict_writer = csv.DictWriter(output_file, keys) dict_writer.writeheader() dict_writer.writerows(orders)
class TestQuoteHelpers: """wrapper to test quote architecture in order""" test_ticker = CONFIG.get('FETCH', 'test_ticker') fake_ticker = CONFIG.get('FETCH', 'fake_ticker') rh_obj = Robinhood() def test_quote_endpoint(self, config=CONFIG): """get raw data from robinhood to test against""" global TEST_QUOTE TEST_QUOTE = helpers.fetch_REST_directly('quotes', self.test_ticker, config) def test_validate_quote(self): """validate fetcher""" data = self.rh_obj.quote_data(self.test_ticker) if data['updated_at'] == TEST_QUOTE['updated_at']: assert data == TEST_QUOTE else: for key in data.keys(): #SKIP PRICE DATA if key in TESTABLE_KEYS: assert data[key] == TEST_QUOTE[key] def test_validate_fail_quote(self): """validate bad-path exception""" with pytest.raises(NameError): data = self.rh_obj.quote_data(self.fake_ticker) def test_validate_get_quote(self): """validate `get_quote` call""" data = self.rh_obj.get_quote(self.test_ticker) assert data == TEST_QUOTE['symbol'] @flaky def test_validate_ask_price(self): """validate `ask_price` call""" data = self.rh_obj.ask_price(self.test_ticker) quote = self.rh_obj.quote_data(self.test_ticker) assert data == quote['ask_price'] @flaky def test_validate_ask_size(self): """validate `ask_size` call""" data = self.rh_obj.ask_size(self.test_ticker) quote = self.rh_obj.quote_data(self.test_ticker) assert data == quote['ask_size'] @flaky def test_validate_bid_price(self): """validate `bid_price` call""" data = self.rh_obj.bid_price(self.test_ticker) quote = self.rh_obj.quote_data(self.test_ticker) assert data == quote['bid_price'] @flaky def test_validate_bid_size(self): """validate `bid_size` call""" data = self.rh_obj.bid_size(self.test_ticker) quote = self.rh_obj.quote_data(self.test_ticker) assert data == quote['bid_size'] @flaky def test_validate_last_trade_price(self): """validate `last_trade_price` call""" data = self.rh_obj.last_trade_price(self.test_ticker) quote = self.rh_obj.quote_data(self.test_ticker) assert data == quote['last_trade_price'] def test_validate_previous_close(self): """validate `previous_close` call""" data = self.rh_obj.previous_close(self.test_ticker) assert data == TEST_QUOTE['previous_close'] def test_validate_previous_close_date(self): """validate `previous_close_date` call""" data = self.rh_obj.previous_close_date(self.test_ticker) assert data == TEST_QUOTE['previous_close_date'] def test_validate_adjusted_previous_close(self): """validate `adjusted_previous_close` call""" data = self.rh_obj.adjusted_previous_close(self.test_ticker) assert data == TEST_QUOTE['adjusted_previous_close'] def test_validate_symbol(self): """validate `symbol` call""" data = self.rh_obj.symbol(self.test_ticker) assert data == TEST_QUOTE['symbol'] @flaky def test_validate_last_updated_at(self): """validate `last_updated_at` call""" data = self.rh_obj.last_updated_at(self.test_ticker) quote = self.rh_obj.quote_data(self.test_ticker) assert data == quote['updated_at']
def run_trader(): try: print("running trader at: " + str(datetime.datetime.now())) message = "running trader at: " + str(datetime.datetime.now()) success = True rh = Robinhood() success = rh.marketOpenCheck() if not success: print('markets are closed') message += '\nmarkets are closed' else: print('markets are open') message += '\nmarkets are open' if success: success = rh.login(username=rhuser, password=rhpass) if success: print('login succesful') message += '\nlogin succesful' else: print('login unsuccesful') message += '\nlogin unsuccesful' if success: #exit extra postions openPositions = rh.securities_owned()['results'] sellOrders = {} for position in openPositions: instrumentURL = position['instrument'] positionTicker = rh.get_url(instrumentURL)['symbol'] positionQuantity = position['quantity'] if (positionTicker != 'SPY') and (positionTicker != 'TLT'): print('position in ', positionTicker, ' is not needed, selling') stock_instrument = rh.instruments(positionTicker)[0] sellOrders[ positionTicker] = rh.place_immediate_market_order( instrumentURL, positionTicker, 'gfd', positionQuantity, 'sell') if sellOrders == {}: print('no extra positions found to close') message += '\nno extra positions found to close' else: print(sellOrders) orderOutcome = 'unresolved' while orderOutcome != 'resolved': remainingUnresolved = False for order in sellOrders: orderDetail = sellOrders[order] orderDetail['status'] = rh.check_order_status( orderDetail['url']) if orderDetail['status'] == 'unresolved': remainingUnresolved = True if not remainingUnresolved: orderOutcome = 'resolved' else: print('remaining unresolved orders, waiting') message += '\nremaining unresolved orders, waiting' time.sleep(60) for order in sellOrders: orderDetail = sellOrders[order] if orderDetail['status'] == 'failure': success = False if not success: print('unable to sell extra positions correctly') message += '\nunable to sell extra positions correctly' if success: #get portfolio current value portfolioValue = rh.equity() print('portfolioValue =', portfolioValue) message += '\nportfolioValue = ' message += str(portfolioValue) #allocate portfolio spyAllocationPercentage = calcAlloc(rh) tltAllocationPercentage = 1 - spyAllocationPercentage print('spyAllocationPercentage = ', spyAllocationPercentage) message += '\nspyAllocationPercentage = ' message += str(spyAllocationPercentage) print('tltAllocationPercentage = ', tltAllocationPercentage) message += '\ntltAllocationPercentage = ' message += str(tltAllocationPercentage) spyTargetAllocation = spyAllocationPercentage * portfolioValue tltTargetAllocation = tltAllocationPercentage * portfolioValue print('spyTargetAllocation = ', spyTargetAllocation) message += '\nspyTargetAllocation = ' message += str(spyTargetAllocation) print('tltTargetAllocation = ', tltTargetAllocation) message += '\ntltTargetAllocation = ' message += str(tltTargetAllocation) #get pricing data spyAskPrice = rh.ask_price('SPY') spyBidPrice = rh.bid_price('SPY') spyAvgCost = (spyAskPrice + spyBidPrice) / 2 spyBuyPrice = spyAskPrice + (spyAskPrice - spyBidPrice) spySellPrice = spyBidPrice - (spyAskPrice - spyBidPrice) print('spyAskPrice = ', spyAskPrice) message += '\nspyAskPrice = ' message += str(spyAskPrice) print('spyBidPrice = ', spyBidPrice) message += '\nspyBidPrice = ' message += str(spyBidPrice) tltAskPrice = rh.ask_price('TLT') tltBidPrice = rh.bid_price('TLT') tltAvgCost = (tltAskPrice + tltBidPrice) / 2 tltBuyPrice = tltAskPrice + (tltAskPrice - tltBidPrice) tltSellPrice = tltBidPrice - (tltAskPrice - tltBidPrice) print('tltAskPrice = ', tltAskPrice) message += '\ntltAskPrice = ' message += str(tltAskPrice) print('tltBidPrice = ', tltBidPrice) message += '\ntltBidPrice = ' message += str(tltBidPrice) #recommend position sizes #[spyTargetShares,tltTargetShares] = recommendTarget(portfolioValue,spyAllocationPercentage,tltAllocationPercentage,spyBuyPrice,tltBuyPrice) [spyTargetShares, tltTargetShares] = recommendInitialTarget( portfolioValue, spyAllocationPercentage, tltAllocationPercentage, spyBuyPrice, tltBuyPrice) print('spyTargetShares = ', spyTargetShares) message += '\nspyTargetShares = ' message += str(spyTargetShares) print('tltTargetShares = ', tltTargetShares) message += '\ntltTargetShares = ' message += str(tltTargetShares) targetPurchaseCost = targetTotalCost(spyTargetShares, tltTargetShares, spyBuyPrice, tltBuyPrice) spyTargetAllocationPercentage = allocationPercentage( spyTargetShares, spyBuyPrice, targetPurchaseCost) tltTargetAllocationPercentage = allocationPercentage( tltTargetShares, tltBuyPrice, targetPurchaseCost) print('spyTargetAllocationPercentage = ', spyTargetAllocationPercentage) message += '\nspyTargetAllocationPercentage = ' message += str(spyTargetAllocationPercentage) print('tltTargetAllocationPercentage = ', tltTargetAllocationPercentage) message += '\ntltTargetAllocationPercentage = ' message += str(tltTargetAllocationPercentage) targetLoss = allocationLoss(spyTargetAllocationPercentage, spyAllocationPercentage, tltTargetAllocationPercentage, tltAllocationPercentage) print('target loss = ', targetLoss) targetRemainingCash = portfolioValue - targetPurchaseCost print('targetPurchaseCost = ', targetPurchaseCost) message += '\ntargetPurchaseCost = ' message += str(targetPurchaseCost) print('targetRemainingCash = ', targetRemainingCash) message += '\ntargetRemainingCash = ' message += str(targetRemainingCash) #detemine required rebalancing spyRequired = spyTargetShares tltRequired = tltTargetShares for position in openPositions: instrumentURL = position['instrument'] positionTicker = rh.get_url(instrumentURL)['symbol'] positionQuantity = float(position['quantity']) if (positionTicker == 'SPY'): spyRequired = spyTargetShares - positionQuantity if (positionTicker == 'TLT'): tltRequired = tltTargetShares - positionQuantity print('spyRequired = ', spyRequired) message += '\nspyRequired = ' message += str(spyRequired) print('tltRequired = ', tltRequired) message += '\ntltRequired = ' message += str(tltRequired) spyInstrumentUrl = (rh.instruments('SPY')[0])['url'] tltInstrumentUrl = (rh.instruments('TLT')[0])['url'] if success: #sell positions if spyRequired < 0.0: print('selling ', -spyRequired, ' of SPY') spySellOrder = rh.place_immediate_market_order( spyInstrumentUrl, 'SPY', 'gfd', -spyRequired, 'sell') print(spySellOrder) orderOutcome = 'unresolved' while orderOutcome != 'resolved': remainingUnresolved = False orderResponse = rh.check_order_status(spySellOrder['url']) if orderResponse == 'unresolved': remainingUnresolved = True if not remainingUnresolved: orderOutcome = 'resolved' else: print('remaining unresolved spySell, waiting') message += '\nremaining unresolved spySell, waiting' time.sleep(60) if orderResponse == 'failure': success = False if not success: print('unable to sell required spy') message += '\nunable to sell required spy' if success: if tltRequired < 0.0: print('selling ', -tltRequired, ' of TLT') tltSellOrder = rh.place_immediate_market_order( tltInstrumentUrl, 'TLT', 'gfd', -tltRequired, 'sell') print(tltSellOrder) orderOutcome = 'unresolved' while orderOutcome != 'resolved': remainingUnresolved = False orderResponse = rh.check_order_status(tltSellOrder['url']) if orderResponse == 'unresolved': remainingUnresolved = True if not remainingUnresolved: orderOutcome = 'resolved' else: print('remaining unresolved tltSell, waiting') message += '\nremaining unresolved tltSell, waiting' time.sleep(60) if orderResponse == 'failure': success = False if not success: print('unable to sell required tlt') message += '\nunable to sell required tlt' #buy positions if success: if spyRequired > 0.0: print('buying ', spyRequired, ' of SPY') spyBuyOrder = rh.place_immediate_market_order( spyInstrumentUrl, 'SPY', 'gfd', spyRequired, 'buy', round(spyBuyPrice, 3)) print(spyBuyOrder) orderOutcome = 'unresolved' while orderOutcome != 'resolved': remainingUnresolved = False orderResponse = rh.check_order_status(spyBuyOrder['url']) if orderResponse == 'unresolved': remainingUnresolved = True if not remainingUnresolved: orderOutcome = 'resolved' else: print('remaining unresolved spyBuy, waiting') message += '\nremaining unresolved spyBuy, waiting' time.sleep(60) if orderResponse == 'failure': success = False if not success: print('unable to buy required spy') message += '\nunable to buy required spy' if success: if tltRequired > 0.0: print('buying ', tltRequired, ' of TLT') tltBuyOrder = rh.place_immediate_market_order( tltInstrumentUrl, 'TLT', 'gfd', tltRequired, 'buy', round(tltBuyPrice, 3)) print(tltBuyOrder) orderOutcome = 'unresolved' while orderOutcome != 'resolved': remainingUnresolved = False orderResponse = rh.check_order_status(tltBuyOrder['url']) if orderResponse == 'unresolved': remainingUnresolved = True if not remainingUnresolved: orderOutcome = 'resolved' else: print('remaining unresolved tltBuy, waiting') message += '\nremaining unresolved tltBuy, waiting' time.sleep(60) if orderResponse == 'failure': success = False if not success: print('unable to buy required tlt') message += '\nunable to buy required tlt' if success: success = rh.logout() if not success: print('unable to logout') message += '\nunable to logout' else: print('succesfully logged out') message += '\nsuccesfully logged out' send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader log ' + str(datetime.datetime.now())), message) except Exception as e: print("Unexpected error:", str(e)) send_email(mailgun_domain, mailgun_api_key, diag_email_dest, ('resiliant-trader log ' + str(datetime.datetime.now())), ("Unexpected error: " + str(e))) raise