class RobinhoodShell(cmd.Cmd): intro = 'Welcome to the Robinhood shell. Type help or ? to list commands.\n' prompt = '> ' # API Object trader = None # Cache file used to store instrument cache instruments_cache_file = 'instruments.data' # Maps Symbol to Instrument URL instruments_cache = {} # Maps URL to Symbol instruments_reverse_cache = {} # Cache file used to store instrument cache watchlist_file = 'watchlist.data' # Auth file auth_file = 'auth.data' # List of stocks in watchlist watchlist = [] def _save_auth_data(self): auth_data = {} auth_data['device_token'] = self.trader.device_token auth_data['auth_token'] = self.trader.auth_token auth_data['refresh_token'] = self.trader.refresh_token open(self.auth_file, 'w').write(json.dumps(auth_data)) def __init__(self): cmd.Cmd.__init__(self) self.trader = Robinhood() # Robinhood now uses 2FA # The workflow we use is as follows # If we find auth token in auth.data - try to see if it still works # If yes, continue # If no, try to refresh the token using refresh token # If it still fails, we need to relogin with 2FA try: data = open(self.auth_file).read() auth_data = json.loads(data) if 'auth_token' in auth_data: self.trader.device_token = auth_data['device_token'] self.trader.auth_token = auth_data['auth_token'] self.trader.refresh_token = auth_data['refresh_token'] self.trader.headers['Authorization'] = 'Bearer ' + self.trader.auth_token try: self.trader.user() except: del self.trader.headers['Authorization'] self.trader.relogin_oauth2() self._save_auth_data() except: challenge_type = 'email' if CHALLENGE_TYPE == 'sms': challenge_type = 'sms' self.trader.login(username = USERNAME, password = PASSWORD, challenge_type = challenge_type) self._save_auth_data() try: data = open(self.instruments_cache_file).read() self.instruments_cache = json.loads(data) for k in self.instruments_cache: self.instruments_reverse_cache[self.instruments_cache[k]] = k except: pass try: data = open(self.watchlist_file).read() self.watchlist = json.loads(data) except: pass # nytime = parser.parse('2018-06-15T23:14:15Z').astimezone(to_zone) # from dateutil import parser # ----- basic commands ----- def do_l(self, arg): 'Lists current portfolio' t = Terminal() portfolio = self.trader.portfolios() if portfolio['extended_hours_equity']: equity = float(portfolio['extended_hours_equity']) else: equity = float(portfolio['equity']) eq = '%.2f' % equity previous_close = float(portfolio['adjusted_equity_previous_close']) change = equity - previous_close change_pct = '%.2f' % (change/previous_close * 100.0) # format change = f"{change:.2f}" # colorize change_pct = color_data(change_pct) change = color_data(change) account_details = self.trader.get_account() if 'margin_balances' in account_details: buying_power = account_details['margin_balances']['unallocated_margin_cash'] account_table = SingleTable([['Portfolio Value','Change','Buying Power'],[eq, change+' ('+change_pct+'%)', buying_power]],'Account') print((account_table.table)) # Load Stocks positions = self.trader.securities_owned() instruments = [position['instrument'] for position in positions['results']] symbols = [self.get_symbol(position['instrument']) for position in positions['results']] market_data = self.trader.get_stock_marketdata(instruments) table_data = [] table_data.append(["Symbol", "Last", "Shares", "Equity", "Avg Cost", "Return" , "Day", "EquityChange", "Day %"]) i = 0 for position in positions['results']: quantity = int(float(position['quantity'])) symbol = self.get_symbol(position['instrument']) price = market_data[i]['last_trade_price'] total_equity = float(price) * quantity buy_price = float(position['average_buy_price']) p_l = f"{total_equity - (buy_price * quantity):.2f}" total_equity = f"{total_equity:.2f}" buy_price = f"{buy_price:.2f}" day_change = f"{float(market_data[i]['last_trade_price']) - float(market_data[i]['previous_close']):.2f}" day_change_q_val = f"{float(quantity) * float(day_change):.2f}" day_change_pct = f"{float(day_change) / float(market_data[i]['previous_close']) * 100:.2f}" price = f"{float(price):.2f}" table_data.append([ symbol, price, quantity, total_equity, buy_price, color_data(p_l), color_data(day_change), color_data(day_change_q_val), color_data(day_change_pct) ]) i += 1 table = SingleTable(table_data,'Portfolio') table.inner_row_border = True table.justify_columns = {0: 'center' } print((table.table)) def do_lo(self, arg): 'Lists current options portfolio' # Load Options options_t_data=[] option_positions = self.trader.options_owned() options_table = SingleTable(options_t_data,'Options') options_table.inner_row_border = True options_table.justify_columns = {0: 'center' } options_t_data.append(["Symbol","Type","Experation","Strike", "Price", "QTY", "Equity", "Cost", "Total Return","Today"]) for op in option_positions: quantity = float(op['quantity']) if quantity == 0: continue cost = float(op['average_price']) if op['type'] == 'short': quantity = -quantity cost = -cost instrument = op['option'] option_data = self.trader.session.get(instrument).json() # skip expired -- verify when it changes state day of or, after market close on expieration if option_data['state'] == "expired": continue expiration_date = option_data['expiration_date'] strike = float(option_data['strike_price']) type = option_data['type'] symbol = op['chain_symbol'] option_type = str(type).upper() expiration = expiration_date strike_price = '$'+str(strike) info = self.trader.get_option_marketdata(instrument) last_price = float(info['adjusted_mark_price']) total_equity = (100 * last_price) * quantity change = total_equity - (float(cost) * quantity) change_pct = '{:04.2f}'.format(change / float(cost) * 100) day_change = float(info['adjusted_mark_price']) - float(info['previous_close_price']) day_pct = '{:04.2f}'.format((day_change / float(info['previous_close_price']) ) * 100) # format after calc day_change = f"{day_change:.3f}" options_t_data.append([ symbol,option_type, expiration, strike_price , last_price, quantity, total_equity, cost, color_data(change) +' ('+ color_data(change_pct) +'%)', color_data(day_change) +' ('+ color_data(day_pct) +'%)' ]) print((options_table.table)) def do_w(self, arg): 'Show watchlist w \nAdd to watchlist w a <symbol> \nRemove from watchlist w r <symbols>' parts = re.split('\W+',arg.upper()) if len(parts) >= 2: if parts[0] == 'A': for p in parts[1:]: if p not in self.watchlist: self.watchlist.append(p.strip()) if parts[0] == 'R': self.watchlist = [r for r in self.watchlist if r not in parts[1:]] print("Done") else: watch_t_data=[] watch_table = SingleTable(watch_t_data,'Watch List') watch_table.inner_row_border = True watch_table.justify_columns = {0: 'center', 1: 'center', 2: 'center', 3:'center',4: 'center'} watch_t_data.append(["Symbol","Ask Price", "Open", "Today", "%"]) if len(self.watchlist) > 0: instruments = [self.get_instrument(s)['url'] for s in self.watchlist] raw_data = self.trader.get_stock_marketdata(instruments) quotes_data = {} for quote in raw_data: day_change = float(quote['last_trade_price']) - float(quote['previous_close']) day_change_pct = '{:05.2f}'.format(( day_change / float(quote['previous_close']) ) * 100) watch_t_data.append([ quote['symbol'], '{:05.2f}'.format(float(quote['last_trade_price'])), '{:05.2f}'.format(float(quote['previous_close'])), color_data(day_change), color_data(day_change_pct) ]) print((watch_table.table)) else: print("Watchlist empty!") def do_b(self, arg): 'Buy stock b <symbol> <quantity> <price>' parts = arg.split() if len(parts) >= 2 and len(parts) <= 3: symbol = parts[0].upper() quantity = parts[1] if len(parts) == 3: price = float(parts[2]) else: price = 0.0 stock_instrument = self.get_instrument(symbol) if not stock_instrument['url']: print("Stock not found") return res = self.trader.place_buy_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print("Error executing order") try: data = res.json() if 'detail' in data: print(data['detail']) except: pass else: print("Done") else: print("Bad Order") def do_s(self, arg): 'Sell stock s <symbol> <quantity> <?price>' parts = arg.split() if len(parts) >= 2 and len(parts) <= 3: symbol = parts[0].upper() quantity = parts[1] if len(parts) == 3: price = float(parts[2]) else: price = 0.0 stock_instrument = self.get_instrument(symbol) if not stock_instrument['url']: print("Stock not found") return res = self.trader.place_sell_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print("Error executing order") try: data = res.json() if 'detail' in data: print(data['detail']) except: pass else: print("Done") else: print("Bad Order") def do_sl(self, arg): 'Setup stop loss on stock sl <symbol> <quantity> <price>' parts = arg.split() if len(parts) == 3: symbol = parts[0].upper() quantity = parts[1] price = float(parts[2]) stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_stop_loss_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print("Error executing order") try: data = res.json() if 'detail' in data: print(data['detail']) except: pass else: print("Done") else: print("Bad Order") def do_o(self, arg): 'List open orders' open_orders = self.trader.get_open_orders() if open_orders: open_t_data=[] open_table = SingleTable(open_t_data,'open List') open_table.inner_row_border = True open_table.justify_columns = {0: 'center', 1: 'center', 2: 'center', 3:'center',4: 'center'} open_t_data.append( ["index", "symbol", "price", "quantity", "type", "id"]) index = 1 for order in open_orders: if order['trigger'] == 'stop': order_price = order['stop_price'] order_type = "stop loss" else: order_price = order['price'] order_type = order['side']+" "+order['type'] open_t_data.append([ index, self.get_symbol(order['instrument']), order_price, int(float(order['quantity'])), order_type, order['id'], ]) index += 1 print((open_table.table)) else: print("No Open Orders") def do_c(self, arg): 'Cancel open order c <index> or c <id>' order_id = arg.strip() order_index = -1 try: order_index = int(order_id) except: pass if order_index > 0: order_index = order_index - 1 open_orders = self.trader.get_open_orders() if order_index < len(open_orders): order_id = open_orders[order_index]['id'] else: print("Bad index") return try: self.trader.cancel_order(order_id) print("Done") except Exception as e: print("Error executing cancel") print(e) def do_ca(self, arg): 'Cancel all open orders' open_orders = self.trader.get_open_orders() for order in open_orders: try: self.trader.cancel_order(order['id']) except Exception as e: pass print("Done") def do_news(self,arg,show_num=5): if len(arg) == 0: print("Missing symbol") else: news_data = self.trader.get_news(arg.upper()) if news_data['count'] == 0: print("No News available") return for x in range(0,show_num): news_box(news_data['results'][x]['source'], news_data['results'][x]['published_at'], news_data['results'][x]['summary'], news_data['results'][x]['title'],news_data['results'][x]['url']) def do_mp(self, arg): 'Buy as many shares possible by defined max dollar amount: mp <symbol> <max_spend> <?price_limit>' parts = arg.split() if len(parts) >= 2 and len(parts) <= 3: symbol = parts[0].upper() #quantity = parts[1] spend = parts[1] if len(parts) == 3: print("Parts: 3") price_limit = float(parts[2]) else: price_limit = 0.0 try: cur_data = self.trader.quote_data(symbol) last_price = cur_data['last_trade_price'] except: print("Invalid Ticker?") pass return # quote['last_trade_price'] quantity = int(math.floor(float(spend) / float(last_price))) print(("\nBuying %s\n Max Spend: %s\nQTY: %s\n Current Price: %s\nMax Price: %s\n" % (symbol,spend, quantity, last_price, price_limit))) # stock_instrument = self.trader.instruments(symbol)[0] # res = self.trader.place_buy_order(stock_instrument, quantity, price) # if not (res.status_code == 200 or res.status_code == 201): # print "Error executing order" # try: # data = res.json() # if 'detail' in data: # print data['detail'] # except: # pass # else: # print "Done" # else: # print "Bad Order" def do_q(self, arg): 'Get detailed quote for stock: q <symbol(s)>' symbols = re.split('\W+',arg.upper()) if len(arg) == 0: print("Missing symbol(s)") else: instruments = [self.get_instrument(s)['url'] for s in symbols] raw_data = self.trader.get_stock_marketdata(instruments) quotes_data = {} quote_t_data=[] quote_table = SingleTable(quote_t_data,'Quote List') quote_table.inner_row_border = True quote_table.justify_columns = {0: 'center', 1: 'center', 2: 'center', 3:'center',4: 'center'} quote_t_data.append(["Symbol", "Current Price", "Open","Change", "Ask","Bid"]) for quote in raw_data: if not quote: continue day_change = float(quote['last_trade_price']) - float(quote['previous_close']) day_change_pct = ( day_change / float(quote['previous_close']) ) * 100 ask_price = '{:05.2f}'.format(float(quote['ask_price'])) ask_size = quote['ask_size'] bid_price = '{:05.2f}'.format(float(quote['bid_price'])) bid_size = quote['bid_size'] quote_t_data.append([ quote['symbol'], '{:05.2f}'.format(float(quote['last_trade_price'])), '{:05.2f}'.format(float(quote['previous_close'])), color_data(day_change)+' ('+color_data('{:05.2f}'.format(day_change_pct))+'%)', str(ask_price)+' x '+str(ask_size), str(bid_price)+' x '+str(bid_size) ]) print((quote_table.table)) def do_qq(self, arg): 'Get quote for stock q <symbol> or option q <symbol> <call/put> <strike> <(optional) YYYY-mm-dd>' arg = arg.strip().split() try: symbol = arg[0].upper() except: print("Please check arguments again. Format: ") print("Stock: q <symbol>") print("Option: q <symbol> <call/put> <strike> <(optional) YYYY-mm-dd>") type = strike = expiry = None if len(arg) > 1: try: type = arg[1] strike = arg[2] except Exception as e: print("Please check arguments again. Format: ") print("q <symbol> <call/put> <strike> <(optional) YYYY-mm-dd>") try: expiry = arg[3] except: expiry = None arg_dict = {'symbol': symbol, 'type': type, 'expiration_dates': expiry, 'strike_price': strike, 'state': 'active', 'tradability': 'tradable'}; quotes = self.trader.get_option_quote(arg_dict); qquote_t_data=[] qquote_table = SingleTable(qquote_t_data,'Quote List') qquote_table.inner_row_border = True qquote_table.justify_columns = {0: 'center', 1: 'center'} qquote_t_data.append(['expiry', 'price']) for row in quotes: qquote_t_data.append(row) print((qquote_table.table)) else: try: self.trader.print_quote(symbol) except: print("Error getting quote for:", symbol) def do_bye(self, arg): open(self.instruments_cache_file, 'w').write(json.dumps(self.instruments_cache)) open(self.watchlist_file, 'w').write(json.dumps(self.watchlist)) self._save_auth_data() return True # ------ utils -------- def get_symbol(self, url): if not url in self.instruments_reverse_cache: self.add_instrument_from_url(url) return self.instruments_reverse_cache[url] def get_instrument(self, symbol): if not symbol in self.instruments_cache: instruments = self.trader.instruments(symbol) for instrument in instruments: self.add_instrument(instrument['url'], instrument['symbol']) url = '' if symbol in self.instruments_cache: url = self.instruments_cache[symbol] return { 'symbol': symbol, 'url': url } def add_instrument_from_url(self, url): data = self.trader.get_url(url) if 'symbol' in data: symbol = data['symbol'] else: types = { 'call': 'C', 'put': 'P'} symbol = data['chain_symbol'] + ' ' + data['expiration_date'] + ' ' + ''.join(types[data['type']].split('-')) + ' ' + str(float(data['strike_price'])) self.add_instrument(url, symbol) def add_instrument(self, url, symbol): self.instruments_cache[symbol] = url self.instruments_reverse_cache[url] = symbol
from Robinhood import Robinhood #Setup my_trader = Robinhood() #login my_trader.login(username="******", password="******") #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) #Place a buy order (uses market bid price) buy_order = my_trader.place_buy_order(stock_instrument, 1) #Place a sell order sell_order = my_trader.place_sell_order(stock_instrument, 1)
from Robinhood import Robinhood my_trader = Robinhood(username="******", password="******") #get stock information about a stock # Note: for some stock names, more than one instrument # may be returned for a given stock symbol stock_instrument = my_trader.instruments("GEVO")[0] #You can stock information about current bid_price, etc quote_info = my_trader.quote_data("GEVO") #place a buy order (uses market bid price) buy_order = my_trader.place_buy_order(stock_instrument, 1) #place a sell order sell_order = my_trader.place_sell_order(stock_instrument, 1)
class Robinhood_AA (object): def __init__(self): self.start_time = datetime.now() self.my_trader = Robinhood() self.my_trader.login(username=usrnm, password=pssw) self.equity = self.my_trader.equity() self.owned_securities = self.my_trader.securities_owned() self.available_funds = self.my_trader.equity() - sum([x[1]*x[4] for x in self.my_trader.securities_owned()]) self.buy_limit = 120 self.stocks = [] self.ld = 10 ## sell no matter what self.sd = 5 ## sell if positive self.file_path = home_path self.conn = sqlite3.connect(self.file_path+'log.db') self.conn.execute('drop table if exists history') self.conn.execute('''create table history (id int primary key not null, date text not null, activity text not null, stock text not null, gain text not null);''') self.idCount = 1 print('Deleting old files...') # delete old files os.chdir(self.file_path) for f in glob.glob("*.png"): os.remove(f) def today_stocks_to_buy(self): F = FGS('Low Cost', 100, {'minPrice':7,'maxPrice':35}, 'lowcost', self.file_path) stocks = F.find_good_stocks() self.stocks = [x[0] for x in stocks] print(self.stocks) def update_info(self): self.equity = self.my_trader.equity() self.owned_securities = self.my_trader.securities_owned() self.available_funds = self.my_trader.equity() - sum([x[1]*x[4] for x in self.my_trader.securities_owned()]) def current_stock_info(self): self.open_log() try: table = [] for s in self.owned_securities: datetime_format = datetime.strptime(s[2], '%Y-%m-%dT%H:%M:%S.%fZ') duration = datetime.now() - datetime_format table.append([s[0], round((s[4]/s[3]-1) * 100, 2), duration > timedelta(days=5), duration > timedelta(days=10)]) table = sorted(table, key = lambda x: x[1]) self.log.write(tabulate(table, headers = ['Stock', 'Total Gain/Loss', '> {} days', '> {} days'.format(self.sd, self.ld)])) self.log.write('\n') except Exception as e: self.log.write('Can\'t print table: unexpected error {}.\n'.format(e)) self.close_log() def buy_stock(self, stock = None): self.open_log() self.log.write('\nBuying:\n') try: if stock == None: self.log.write('Nothing bought: no stock specified.\n') elif self.available_funds > self.buy_limit: last_price = float(self.my_trader.last_trade_price(stock)) number_to_buy = int(self.buy_limit/last_price) self.my_trader.place_buy_order(self.my_trader.instruments(stock)[0], int(self.buy_limit/last_price)) self.log.write('Buying {} stocks of {} at {} for a total of {}.\n'.format(number_to_buy, stock, last_price, last_price * number_to_buy)) self.conn.execute('insert into history (id,date,activity,stock,gain) values (?, ?, ?, ?, ?)', (self.idCount, datetime.now(), 'BUY', stock, 'N/A')) self.idCount += 1 else: self.log.write('Nothing bought: insufficient funds to buy stock. Need at least {} dollars.\n'.format(self.buy_limit)) except Exception as e: self.log.write('Nothing bought: {}.\n'.format(e)) self.close_log() def auto_buy_stocks(self): self.open_log() self.log.write('\nBuying:\n') try: if self.available_funds < self.buy_limit: self.log.write('Nothing bought: insufficient funds to buy stocks. Need at least {0} dollars.\n'.format(self.buy_limit)) else: for i in range(int(self.available_funds / self.buy_limit)): last_price = float(self.my_trader.last_trade_price(self.stocks[i])) number_to_buy = int(self.buy_limit/last_price) self.my_trader.place_buy_order(self.my_trader.instruments(self.stocks[i])[0], int(self.buy_limit/last_price)) self.log.write('Buying {} stocks of {} at {} for a total of {}.\n'.format(number_to_buy, self.stocks[i], last_price, last_price * number_to_buy)) self.conn.execute('insert into history (id,date,activity,stock,gain) values (?, ?, ?, ?, ?)', (self.idCount, datetime.now(), 'BUY', self.stocks[i], 'N/A')) self.idCount += 1 time.sleep(10) #except Exception as e: except BufferError: self.log.write('Nothing bought: {}.\n'.format(e)) self.close_log() def auto_sell_stocks(self): self.open_log() self.log.write('\nSelling:\n') try: for s in self.owned_securities: datetime_format = datetime.strptime(s[2], '%Y-%m-%dT%H:%M:%S.%fZ') duration = datetime.now() - datetime_format gain = round((s[4]/s[3]-1) * 100, 2) try: if duration > timedelta(days=self.ld): self.my_trader.place_sell_order(self.my_trader.instruments(s[0])[0], s[1]) self.log.write('Selling {}: More than {} days :|\n'.format(s[0], self.ld)) self.conn.execute('insert into history (id,date,activity,stock,gain) values (?, ?, ?, ?, ?)', (self.idCount, datetime.now(), 'SELL', s[0], gain)) self.idCount += 1 elif duration > timedelta(days=self.sd) and gain > 0: self.my_trader.place_sell_order(self.my_trader.instruments(s[0])[0], s[1]) self.log.write('Selling {}: More than {} days and positive :)\n'.format(s[0], self.sd)) self.conn.execute('insert into history (id,date,activity,stock,gain) values (?, ?, ?, ?, ?)', (self.idCount, datetime.now(), 'SELL', s[0], gain)) self.idCount += 1 elif gain > 5: self.my_trader.place_sell_order(self.my_trader.instruments(s[0])[0], s[1]) self.log.write('Selling {}: More than 5% :)\n'.format(s[0])) self.conn.execute('insert into history (id,date,activity,stock,gain) values (?, ?, ?, ?, ?)', (self.idCount, datetime.now(), 'SELL', s[0], gain)) self.idCount += 1 elif gain < -5: self.my_trader.place_sell_order(self.my_trader.instruments(s[0])[0], s[1]) self.log.write('Selling {}: Less than -5% :(\n'.format(s[0])) self.conn.execute('insert into history (id,date,activity,stock,gain) values (?, ?, ?, ?, ?)', (self.idCount, datetime.now(), 'SELL', s[0], gain)) self.idCount += 1 except Exception as e: self.log.write('Couldn\'t sell {}: {}.\n'.format(s[0], e)) except Exception as e: self.log.write('Nothing sold: {}.\n'.format(e)) self.close_log() def new_log(self): # creates new log if different day if os.path.isfile('{}log{}.txt'.format(self.file_path,datetime.now().strftime('%y%m%d'))): pass else: self.log = open('{}log{}.txt'.format(self.file_path,datetime.now().strftime('%y%m%d')),'w') self.log.close() def open_log(self): self.log = open('{}log{}.txt'.format(self.file_path,datetime.now().strftime('%y%m%d')),'a') self.log.write('\n\nRobinhood Status: {}\n\n'.format(datetime.now())) def close_log(self): try: self.log.write('\nTook {} seconds.'.format(datetime.now() - self.start_time)) self.log.close() except Exception as e: print('Couldn\'t close log: {}'.format(e)) def printDB(self, db='log.db'): try: self.log.write('\nDatabase:') cur = sqlite3.connect(db).cursor() self.log.write(' '+str([header[0] for header in cur.execute("select * from history").description][1:])) for entry in cur.fetchall(): self.log.write(entry) cur.close() except Exception as e: print('Couldn\'t print database: {}'.format(e)) def send_email_AA(self): sendEmail(self.file_path, 'Robinhood Operation', ['*****@*****.**'], ['blacklist.txt',self.file_path+'readme.txt',self.file_path+'log.db', self.file_path+'.DS_Store', self.file_path+'log.db-journal'])
class RobinhoodShell(cmd.Cmd): intro = 'Welcome to the Robinhood shell. Type help or ? to list commands.\n' prompt = '> ' # API Object trader = None # Cache file used to store instrument cache instruments_cache_file = 'instruments.data' # Maps Symbol to Instrument URL instruments_cache = {} # Maps URL to Symbol instruments_reverse_cache = {} def __init__(self): cmd.Cmd.__init__(self) self.trader = Robinhood() self.trader.login(username=USERNAME, password=PASSWORD) try: data = open('instruments.data').read() self.instruments_cache = json.loads(data) for k in self.instruments_cache: self.instruments_reverse_cache[self.instruments_cache[k]] = k except: pass # ----- basic commands ----- def do_l(self, arg): 'Lists current portfolio' portfolio = self.trader.portfolios() print 'Equity Value:', portfolio['equity'] account_details = self.trader.get_account() if 'margin_balances' in account_details: print 'Buying Power:', account_details['margin_balances'][ 'unallocated_margin_cash'] positions = self.trader.securities_owned() symbols = [] for position in positions['results']: symbol = self.get_symbol(position['instrument']) symbols.append(symbol) raw_data = self.trader.quotes_data(symbols) quotes_data = {} for quote in raw_data: quotes_data[quote['symbol']] = quote['last_trade_price'] table = BeautifulTable() table.column_headers = [ "symbol", "current price", "quantity", "total equity" ] for position in positions['results']: quantity = int(float(position['quantity'])) symbol = self.get_symbol(position['instrument']) price = quotes_data[symbol] total_equity = float(price) * quantity table.append_row([symbol, price, quantity, total_equity]) print(table) def do_b(self, arg): 'Buy stock b <symbol> <quantity> <price>' parts = arg.split() if len(parts) == 3: symbol = parts[0] quantity = parts[1] price = float(parts[2]) stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_buy_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print "Error executing order" try: data = res.json() if 'detail' in data: print data['detail'] except: pass else: print "Done" else: print "Bad Order" def do_s(self, arg): 'Sell stock s <symbol> <quantity> <price>' parts = arg.split() if len(parts) == 3: symbol = parts[0] quantity = parts[1] price = float(parts[2]) stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_sell_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print "Error executing order" try: data = res.json() if 'detail' in data: print data['detail'] except: pass else: print "Done" else: print "Bad Order" def do_o(self, arg): 'List open orders' open_orders = self.trader.get_open_orders() if open_orders: table = BeautifulTable() table.column_headers = [ "symbol", "price", "quantity", "type", "id" ] for order in open_orders: table.append_row([ self.get_symbol(order['instrument']), order['price'], int(float(order['quantity'])), order['side'], order['id'], ]) print(table) else: print "No Open Orders" def do_c(self, arg): 'Cancel open order c <id>' order_id = arg.strip() try: self.trader.cancel_order(order_id) print "Done" except Exception as e: print "Error executing cancel" print e def do_q(self, arg): 'Get quote for stock q <symbol>' symbol = arg.strip() try: self.trader.print_quote(symbol) except: print "Error getting quote for:", symbol def do_bye(self, arg): open(self.instruments_cache_file, 'w').write(json.dumps(self.instruments_cache)) return True # ------ utils -------- def get_symbol(self, url): if not url in self.instruments_reverse_cache: self.add_instrument_from_url(url) return self.instruments_reverse_cache[url] def add_instrument_from_url(self, url): data = self.trader.get_url(url) symbol = data['symbol'] self.instruments_cache[symbol] = url self.instruments_reverse_cache[url] = symbol
class TKshell(cmd.Cmd): intro = 'Welcome to the Robinhood shell. Type help or ? to list commands.\n' prompt = '> ' # API Object trader = None # Cache file used to store instrument cache instruments_cache_file = 'instruments.data' # Maps Symbol to Instrument URL instruments_cache = {} # Maps URL to Symbol instruments_reverse_cache = {} def __init__(self): cmd.Cmd.__init__(self) self.trader = Robinhood() self.trader.login_prompt() try: data = open('instruments.data').read() self.instruments_cache = json.loads(data) for k in self.instruments_cache: self.instruments_reverse_cache[self.instruments_cache[k]] = k except: pass # ----- basic commands ----- def do_l(self, arg): 'Lists current portfolio' portfolio = self.trader.portfolios() print('Equity Value:', portfolio['equity']) account_details = self.trader.get_account() if 'margin_balances' in account_details: print( 'Buying Power:', account_details['margin_balances']['unallocated_margin_cash']) positions = self.trader.securities_owned() symbols = '' buy_price_data = {} for position in positions['results']: symbol = self.get_symbol(position['instrument']) buy_price_data[symbol] = position['average_buy_price'] symbols += symbol + ',' symbols = symbols[:-1] raw_data = self.trader.quote_data(symbols) quotes_data = {} for quote in raw_data: quotes_data[quote['symbol']] = quote['last_trade_price'] d = [] for position in positions['results']: quantity = int(float(position['quantity'])) symbol = self.get_symbol(position['instrument']) price = quotes_data[symbol] total_equity = float(price) * quantity buy_price = float(buy_price_data[symbol]) p_l = total_equity - buy_price * quantity d.append([symbol, price, quantity, total_equity, buy_price, p_l]) column_headers = [ "symbol", "current price", "quantity", "total equity", "cost basis", "p/l" ] table = tabulate(d, headers=column_headers) print(table) def do_q(self, arg): 'Get quote for stock q <symbol>' symbols = arg.strip() headers = [ 'symbol', 'price', 'bid_size', 'bid_price', 'ask_size', 'ask_price' ] try: data = self.trader.get_quote_list( symbols, 'symbol,last_trade_price,bid_size,bid_price,ask_size,ask_price' ) print(tabulate(data, headers=headers)) except: print("Error getting quote for:", symbols) def do_b(self, arg): 'Buy stock b <symbol> <quantity> <price>' parts = arg.split() if len(parts) == 3: symbol = parts[0] quantity = parts[1] price = round(float(parts[2]), 2) stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_buy_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print("Error executing order") try: data = res.json() if 'detail' in data: print(data['detail']) except: pass else: print("Done") else: print("Bad Order") def do_qb(self, arg): ''' Quick Buy a quick buy is a limit buy which price is set at previous close + 15% * previous candle body :param arg: <symbol> <quantity> :return: order detail ''' parts = arg.split() if len(parts) == 2: symbol = parts[0] quantity = parts[1] d = g_ts.get_intraday(symbol=symbol, interval='5min')[0][-2:-1] o = float(d['open']) c = float(d['close']) price = round(min(o, c) + 0.15 * abs(o - c), 2) stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_buy_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print("Error executing order") try: data = res.json() if 'detail' in data: print(data['detail']) except: pass else: print("Done") else: print("Bad Order") def do_s(self, arg): 'Sell stock s <symbol> <quantity> <price>' parts = arg.split() if len(parts) == 3: symbol = parts[0] quantity = parts[1] price = float(parts[2]) stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_sell_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print("Error executing order") try: data = res.json() if 'detail' in data: print(data['detail']) except: pass else: print("Done") else: print("Bad Order") def do_o(self, arg): 'List open orders' open_orders = self.trader.order_history()['results'][:10] if open_orders: column_headers = [ "index", "symbol", "state", "price", "quantity", "type", "id" ] global g_openorders, g_liststates g_openorders = [] count = 1 for order in open_orders: if order['state'] in g_liststates: g_openorders.append([ count, self.get_symbol(order['instrument']), order['state'], order['price'], int(float(order['quantity'])), order['side'], order['id'] ]) count += 1 g_openorders.reverse() table = tabulate(g_openorders, headers=column_headers) print(table) else: print("No Open Orders") def do_c(self, arg): ''' Cancel an open order by index return in list orders :param arg: :return: ''' order_index = int(arg.strip()) try: self.trader.cancel_order(g_openorders[-order_index][-1]) except Exception as e: print("Error executing cancel\n", e) print(g_openorders[-order_index], "has been cancelled.") def do_u(self, arg): ''' refresh the watch list, combining positions owned with symbol in wl.json :param arg: :return: ''' positions = self.trader.securities_owned() global g_watchlist g_watchlist = [] for position in positions['results']: g_watchlist.append(self.trader.quote_data(position['instrument'])) # TODO maybe add pre-calculated price level in the json file as well with open('wl.json', 'r') as f: d = json.load(f) for each in d: g_watchlist.append(each) print("Watchlist updated") print(tabulate(d)) def do_r(self, arg): ''' rate :param arg: :return: ''' def do_bye(self, arg): open(self.instruments_cache_file, 'w').write(json.dumps(self.instruments_cache)) return True # ------ utils -------- def get_symbol(self, url): if not url in self.instruments_reverse_cache: self.add_instrument_from_url(url) return self.instruments_reverse_cache[url] def add_instrument_from_url(self, url): data = self.trader.get_url(url) symbol = data['symbol'] self.instruments_cache[symbol] = url self.instruments_reverse_cache[url] = symbol
class RobinhoodShell(cmd.Cmd): intro = 'Welcome to the Robinhood shell. Type help or ? to list commands.\n' prompt = '> ' # API Object trader = None # Cache file used to store instrument cache instruments_cache_file = 'instruments.data' # Maps Symbol to Instrument URL instruments_cache = {} # Maps URL to Symbol instruments_reverse_cache = {} # Cache file used to store instrument cache watchlist_file = 'watchlist.data' # List of stocks in watchlist watchlist = [] def __init__(self): cmd.Cmd.__init__(self) self.trader = Robinhood() self.trader.login(username=USERNAME, password=PASSWORD) try: data = open(self.instruments_cache_file).read() self.instruments_cache = json.loads(data) for k in self.instruments_cache: self.instruments_reverse_cache[self.instruments_cache[k]] = k except: pass try: data = open(self.watchlist_file).read() self.watchlist = json.loads(data) except: pass # nytime = parser.parse('2018-06-15T23:14:15Z').astimezone(to_zone) # from dateutil import parser # ----- basic commands ----- def do_l(self, arg): 'Lists current portfolio' portfolio = self.trader.portfolios() if portfolio['extended_hours_equity']: equity = float(portfolio['extended_hours_equity']) else: equity = float(portfolio['equity']) print 'Equity Value: %.2f' % equity previous_close = float(portfolio['adjusted_equity_previous_close']) change = equity - previous_close print '%s%.2f Today (%.2f%%)' % (('+' if change > 0 else ''), change, change / previous_close * 100.0) account_details = self.trader.get_account() if 'margin_balances' in account_details: print 'Buying Power:', account_details['margin_balances'][ 'unallocated_margin_cash'] # Load Stocks positions = self.trader.securities_owned() symbols = [ self.get_symbol(position['instrument']) for position in positions['results'] ] quotes_data = {} if len(symbols) > 0: raw_data = self.trader.quotes_data(symbols) for quote in raw_data: if quote['last_extended_hours_trade_price']: price = quote['last_extended_hours_trade_price'] else: price = quote['last_trade_price'] quotes_data[quote['symbol']] = price table = BeautifulTable() table.column_headers = [ "symbol", "current price", "quantity", "total equity", "cost basis", "p/l" ] for position in positions['results']: quantity = int(float(position['quantity'])) symbol = self.get_symbol(position['instrument']) price = quotes_data[symbol] total_equity = float(price) * quantity buy_price = float(position['average_buy_price']) p_l = total_equity - buy_price * quantity table.append_row( [symbol, price, quantity, total_equity, buy_price, p_l]) print "Stocks:" print(table) # Load Options option_positions = self.trader.options_owned() table = BeautifulTable() table.column_headers = [ "option", "price", "quantity", "equity", "cost basis", "p/l" ] for op in option_positions: quantity = float(op['quantity']) if quantity == 0: continue cost = float(op['average_price']) if op['type'] == 'short': quantity = -quantity cost = -cost instrument = op['option'] option_data = self.trader.session.get(instrument).json() expiration_date = option_data['expiration_date'] strike = float(option_data['strike_price']) type = option_data['type'] symbol = op[ 'chain_symbol'] + ' ' + expiration_date + ' ' + type + ' $' + str( strike) info = self.trader.get_option_marketdata(instrument) last_price = float(info['adjusted_mark_price']) total_equity = (100 * last_price) * quantity change = total_equity - (float(cost) * quantity) table.append_row( [symbol, last_price, quantity, total_equity, cost, change]) print "Options:" print(table) def do_w(self, arg): 'Show watchlist w \nAdd to watchlist w a <symbol> \nRemove from watchlist w r <symbol>' parts = arg.split() if len(parts) == 2: if parts[0] == 'a': self.watchlist.append(parts[1].strip()) if parts[0] == 'r': self.watchlist = [ r for r in self.watchlist if not r == parts[1].strip() ] print "Done" else: table = BeautifulTable() table.column_headers = ["symbol", "current price"] if len(self.watchlist) > 0: raw_data = self.trader.quotes_data(self.watchlist) quotes_data = {} for quote in raw_data: table.append_row( [quote['symbol'], quote['last_trade_price']]) print(table) else: print "Watchlist empty!" def do_b(self, arg): 'Buy stock b <symbol> <quantity> <price>' parts = arg.split() if len(parts) >= 2 and len(parts) <= 3: symbol = parts[0] quantity = parts[1] if len(parts) == 3: price = float(parts[2]) else: price = 0.0 stock_instrument = self.get_instrument(symbol) if not stock_instrument['url']: print "Stock not found" return res = self.trader.place_buy_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print "Error executing order" try: data = res.json() if 'detail' in data: print data['detail'] except: pass else: print "Done" else: print "Bad Order" def do_s(self, arg): 'Sell stock s <symbol> <quantity> <?price>' parts = arg.split() if len(parts) >= 2 and len(parts) <= 3: symbol = parts[0] quantity = parts[1] if len(parts) == 3: price = float(parts[2]) else: price = 0.0 stock_instrument = self.get_instrument(symbol) if not stock_instrument['url']: print "Stock not found" return res = self.trader.place_sell_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print "Error executing order" try: data = res.json() if 'detail' in data: print data['detail'] except: pass else: print "Done" else: print "Bad Order" def do_sl(self, arg): 'Setup stop loss on stock sl <symbol> <quantity> <price>' parts = arg.split() if len(parts) == 3: symbol = parts[0] quantity = parts[1] price = float(parts[2]) stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_stop_loss_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print "Error executing order" try: data = res.json() if 'detail' in data: print data['detail'] except: pass else: print "Done" else: print "Bad Order" def do_o(self, arg): 'List open orders' open_orders = self.trader.get_open_orders() if open_orders: table = BeautifulTable() table.column_headers = [ "index", "symbol", "price", "quantity", "type", "id" ] index = 1 for order in open_orders: if order['trigger'] == 'stop': order_price = order['stop_price'] order_type = "stop loss" else: order_price = order['price'] order_type = order['side'] + " " + order['type'] table.append_row([ index, self.get_symbol(order['instrument']), order_price, int(float(order['quantity'])), order_type, order['id'], ]) index += 1 print(table) else: print "No Open Orders" def do_c(self, arg): 'Cancel open order c <index> or c <id>' order_id = arg.strip() order_index = -1 try: order_index = int(order_id) except: pass if order_index > 0: order_index = order_index - 1 open_orders = self.trader.get_open_orders() if order_index < len(open_orders): order_id = open_orders[order_index]['id'] else: print "Bad index" return try: self.trader.cancel_order(order_id) print "Done" except Exception as e: print "Error executing cancel" print e def do_ca(self, arg): 'Cancel all open orders' open_orders = self.trader.get_open_orders() for order in open_orders: try: self.trader.cancel_order(order['id']) except Exception as e: pass print "Done" def do_q(self, arg): 'Get quote for stock q <symbol> or option q <symbol> <call/put> <strike> <(optional) YYYY-mm-dd>' arg = arg.strip().split() try: symbol = arg[0] except: print "Please check arguments again. Format: " print "Stock: q <symbol>" print "Option: q <symbol> <call/put> <strike> <(optional) YYYY-mm-dd>" type = strike = expiry = None if len(arg) > 1: try: type = arg[1] strike = arg[2] except Exception as e: print "Please check arguments again. Format: " print "q <symbol> <call/put> <strike> <(optional) YYYY-mm-dd>" try: expiry = arg[3] except: expiry = None arg_dict = { 'symbol': symbol, 'type': type, 'expiration_dates': expiry, 'strike_price': strike, 'state': 'active', 'tradability': 'tradable' } quotes = self.trader.get_option_quote(arg_dict) table = BeautifulTable() table.column_headers = ['expiry', 'price'] for row in quotes: table.append_row(row) print table else: try: self.trader.print_quote(symbol) except: print "Error getting quote for:", symbol def do_bye(self, arg): open(self.instruments_cache_file, 'w').write(json.dumps(self.instruments_cache)) open(self.watchlist_file, 'w').write(json.dumps(self.watchlist)) return True # ------ utils -------- def get_symbol(self, url): if not url in self.instruments_reverse_cache: self.add_instrument_from_url(url) return self.instruments_reverse_cache[url] def get_instrument(self, symbol): if not symbol in self.instruments_cache: instruments = self.trader.instruments(symbol) for instrument in instruments: self.add_instrument(instrument['url'], instrument['symbol']) url = '' if symbol in self.instruments_cache: url = self.instruments_cache[symbol] return {'symbol': symbol, 'url': url} def add_instrument_from_url(self, url): data = self.trader.get_url(url) if 'symbol' in data: symbol = data['symbol'] else: types = {'call': 'C', 'put': 'P'} symbol = data['chain_symbol'] + ' ' + data[ 'expiration_date'] + ' ' + ''.join( types[data['type']].split('-')) + ' ' + str( float(data['strike_price'])) self.add_instrument(url, symbol) def add_instrument(self, url, symbol): self.instruments_cache[symbol] = url self.instruments_reverse_cache[url] = symbol
position = div.find(FEAR_AND_GREED_PHRASE) position = position + len(FEAR_AND_GREED_PHRASE) current_fear_and_greed_index = int(div[position:position + 3].strip()) print(current_fear_and_greed_index) print(type(current_fear_and_greed_index)) others_are_greedy = current_fear_and_greed_index >= GREED_THRESOLD others_are_fearful = current_fear_and_greed_index <= FEAR_THRESOLD # robinhood setup robinhood = Robinhood() logged_in = robinhood.login(username=config.username, password=config.password) instrument = robinhood.instruments(INTSTRUMENT_TO_BUY)[0] print("Printing stock instrument info") print(stock) quote = robinhood.quote_data(INTSTRUMENT_TO_BUY) print("Printing quote data for {}".format(INTSTRUMENT_TO_BUY)) print(quote) if others_are_greedy: # sell sell_order = robinhood.place_sell_order(instrument, 1) if others_are_fearful: # buy buy_order = robinhood.place_buy_order(instrument, 1)
class RobinhoodShell(cmd.Cmd): intro = 'Welcome to the Robinhood shell. Type help or ? to list commands.\n' prompt = '> ' # API Object trader = None # Cache file used to store instrument cache instruments_cache_file = 'instruments.data' # Maps Symbol to Instrument URL instruments_cache = {} # Maps URL to Symbol instruments_reverse_cache = {} # Cache file used to store instrument cache watchlist_file = 'watchlist.data' # List of stocks in watchlist watchlist = [] def __init__(self): cmd.Cmd.__init__(self) self.trader = Robinhood() self.trader.login(username=USERNAME, password=PASSWORD) try: data = open(self.instruments_cache_file).read() self.instruments_cache = json.loads(data) for k in self.instruments_cache: self.instruments_reverse_cache[self.instruments_cache[k]] = k except: pass try: data = open(self.watchlist_file).read() self.watchlist = json.loads(data) except: pass # ----- basic commands ----- def do_l(self, arg): 'Lists current portfolio' portfolio = self.trader.portfolios() print 'Equity Value:', portfolio['equity'] account_details = self.trader.get_account() if 'margin_balances' in account_details: print 'Buying Power:', account_details['margin_balances']['unallocated_margin_cash'] positions = self.trader.securities_owned() symbols = [] buy_price_data = {} for position in positions['results']: symbol = self.get_symbol(position['instrument']) buy_price_data[symbol] = position['average_buy_price'] symbols.append(symbol) quotes_data = {} if len(symbols) > 0: raw_data = self.trader.quotes_data(symbols) for quote in raw_data: quotes_data[quote['symbol']] = quote['last_trade_price'] table = BeautifulTable() table.column_headers = ["symbol", "current price", "quantity", "total equity", "cost basis", "p/l"] for position in positions['results']: quantity = int(float(position['quantity'])) symbol = self.get_symbol(position['instrument']) price = quotes_data[symbol] total_equity = float(price) * quantity buy_price = float(buy_price_data[symbol]) p_l = total_equity - buy_price * quantity table.append_row([symbol, price, quantity, total_equity, buy_price, p_l]) print(table) def do_w(self, arg): 'Show watchlist w \nAdd to watchlist w a <symbol> \nRemove from watchlist w r <symbol>' parts = arg.split() if len(parts) == 2: if parts[0] == 'a': self.watchlist.append(parts[1].strip()) if parts[0] == 'r': self.watchlist = [r for r in self.watchlist if not r == parts[1].strip()] print "Done" else: table = BeautifulTable() table.column_headers = ["symbol", "current price"] if len(self.watchlist) > 0: raw_data = self.trader.quotes_data(self.watchlist) quotes_data = {} for quote in raw_data: table.append_row([quote['symbol'], quote['last_trade_price']]) print(table) else: print "Watchlist empty!" def do_b(self, arg): 'Buy stock b <symbol> <quantity> <price>' parts = arg.split() if len(parts) >= 2 and len(parts) <= 3: symbol = parts[0] quantity = parts[1] if len(parts) == 3: price = float(parts[2]) else: price = 0.0 stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_buy_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print "Error executing order" try: data = res.json() if 'detail' in data: print data['detail'] except: pass else: print "Done" else: print "Bad Order" def do_s(self, arg): 'Sell stock s <symbol> <quantity> <?price>' parts = arg.split() if len(parts) >= 2 and len(parts) <= 3: symbol = parts[0] quantity = parts[1] if len(parts) == 3: price = float(parts[2]) else: price = 0.0 stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_sell_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print "Error executing order" try: data = res.json() if 'detail' in data: print data['detail'] except: pass else: print "Done" else: print "Bad Order" def do_sl(self, arg): 'Setup stop loss on stock sl <symbol> <quantity> <price>' parts = arg.split() if len(parts) == 3: symbol = parts[0] quantity = parts[1] price = float(parts[2]) stock_instrument = self.trader.instruments(symbol)[0] res = self.trader.place_stop_loss_order(stock_instrument, quantity, price) if not (res.status_code == 200 or res.status_code == 201): print "Error executing order" try: data = res.json() if 'detail' in data: print data['detail'] except: pass else: print "Done" else: print "Bad Order" def do_o(self, arg): 'List open orders' open_orders = self.trader.get_open_orders() if open_orders: table = BeautifulTable() table.column_headers = ["index", "symbol", "price", "quantity", "type", "id"] index = 1 for order in open_orders: table.append_row([ index, self.get_symbol(order['instrument']), order['price'], int(float(order['quantity'])), order['side'], order['id'], ]) index += 1 print(table) else: print "No Open Orders" def do_c(self, arg): 'Cancel open order c <index> or c <id>' order_id = arg.strip() order_index = -1 try: order_index = int(order_id) except: pass if order_index > 0: order_index = order_index - 1 open_orders = self.trader.get_open_orders() if order_index < len(open_orders): order_id = open_orders[order_index]['id'] else: print "Bad index" return try: self.trader.cancel_order(order_id) print "Done" except Exception as e: print "Error executing cancel" print e def do_ca(self, arg): 'Cancel all open orders' open_orders = self.trader.get_open_orders() for order in open_orders: try: self.trader.cancel_order(order['id']) except Exception as e: pass print "Done" def do_q(self, arg): 'Get quote for stock q <symbol>' symbol = arg.strip() try: self.trader.print_quote(symbol) except: print "Error getting quote for:", symbol def do_bye(self, arg): open(self.instruments_cache_file, 'w').write(json.dumps(self.instruments_cache)) open(self.watchlist_file, 'w').write(json.dumps(self.watchlist)) return True # ------ utils -------- def get_symbol(self, url): if not url in self.instruments_reverse_cache: self.add_instrument_from_url(url) return self.instruments_reverse_cache[url] def add_instrument_from_url(self, url): data = self.trader.get_url(url) symbol = data['symbol'] self.instruments_cache[symbol] = url self.instruments_reverse_cache[url] = symbol