class RHTrader: """ Algorithmic trader using Robinhood API to enter positions based on RSI period and historical prices. """ 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 populate(self): historical_quotes = self.rh.get_historical_quotes( "F", "5minute", "day") index = 0 support = 0 resistance = 0 for key in historical_quotes["results"][0]["historicals"]: if index >= len(historical_quotes["results"][0]["historicals"]) - ( self.rsiPeriod + 1): if (index >= (self.rsiPeriod - 1) and datetime.strptime( key['begins_at'], '%Y-%m-%dT%H:%M:%SZ').minute == 0): support = 0 resistance = 0 print("Resetting support and resistance") if float(key['close_price']) < support or support == 0: support = float(key['close_price']) print("Current Support is : ") print(support) if float(key['close_price']) > resistance: resistance = float(key['close_price']) print("Current Resistance is : ") print(resistance) self.closePrices.append(float(key['close_price'])) index += 1 self.data = np.array(self.closePrices) def execute(self, sc): if len(self.closePrices) > self.rsiPeriod: # Calculate RSI rsi = ti.rsi(self.data, period=self.rsiPeriod) instrument = self.rh.instruments("F")[0] # If rsi is less than or equal to 30 buy if rsi[len(rsi) - 1] <= 30 and not self.enteredPosition: print("Buying RSI is below 30!") self.rh.place_buy_order(instrument, 1) self.enteredPosition = True # Sell when RSI reaches 70 if rsi[len(rsi) - 1] >= 70 and self.enteredPosition: print("Selling RSI is above 70!") self.rh.place_sell_order(instrument, 1) self.enteredPosition = False print(rsi) # call this method again every 5 minutes for new price changes self.s.enter(300, 1, self.execute, (sc, )) def run(self): self.s.enter(1, 1, self.execute, (self.s, )) self.s.run()
def watcher(): global graph_msg, graph_min, graph_max rh = Robinhood() rh.login(username=rh_user, password=rh_pass, qr_code=rh_qr) raw_result = rh.positions() result = raw_result['results'] shares_total = [] port_msg = f"Your portfolio ({rh.get_account()['account_number']}):\n" loss_output = 'Loss:' profit_output = 'Profit:' loss_total = [] profit_total = [] graph_msg = None # initiates a variable graph_msg as None for looped condition below n = 0 n_ = 0 for data in result: share_id = str(data['instrument'].split('/')[-2]) buy = round(float(data['average_buy_price']), 2) shares_count = int(data['quantity'].split('.')[0]) if shares_count != 0: n = n + 1 n_ = n_ + shares_count else: continue raw_details = rh.get_quote(share_id) share_name = raw_details['symbol'] call = raw_details['instrument'] share_full_name = loads(get(call).text)['simple_name'] total = round(shares_count * float(buy), 2) shares_total.append(total) current = round(float(raw_details['last_trade_price']), 2) current_total = round(shares_count * current, 2) difference = round(float(current_total - total), 2) if difference < 0: loss_output += ( f'\n{share_full_name}:\n{shares_count} shares of {share_name} at ${buy} Currently: ${current}\n' f'Total bought: ${total} Current Total: ${current_total}' f'\nLOST ${-difference}\n') loss_total.append(-difference) else: profit_output += ( f'\n{share_full_name}:\n{shares_count} shares of {share_name} at ${buy} Currently: ${current}\n' f'Total bought: ${total} Current Total: ${current_total}' f'\nGained ${difference}\n') profit_total.append(difference) if graph_min and graph_max: graph_min = float(graph_min) graph_max = float(graph_max) if difference > graph_max or difference < -graph_min: time_now = datetime.now() metrics = time_now - timedelta(days=7) numbers = [] historic_data = (rh.get_historical_quotes( share_name, '10minute', 'week')) historical_values = historic_data['results'][0]['historicals'] for close_price in historical_values: numbers.append(round(float(close_price['close_price']), 2)) fig, ax = plt.subplots() if difference > graph_max: plt.title( f"Stock Price Trend for {share_full_name}\nShares: {shares_count} Profit: ${difference}" ) elif difference < graph_min: plt.title( f"Stock Price Trend for {share_full_name}\nShares: {shares_count} LOSS: ${-difference}" ) plt.xlabel( f"1 Week trend with 10 minutes interval from {metrics.strftime('%m-%d %H:%M')} to " f"{time_now.strftime('%m-%d %H:%M')}") plt.ylabel('Price in USD') ax.plot(numbers, linewidth=1.5) if not path.isdir('img'): mkdir('img') fig.savefig(f"img/{share_full_name}.png", format="png") plt.close( ) # close plt to avoid memory exception when more than 20 graphs are generated # stores graph_msg only if a graph is generated else graph_msg remains None if not graph_msg: # used if not to avoid storing the message repeatedly graph_msg = f"Attached are the graphs for stocks which exceeded a profit of " \ f"${graph_max} or deceeded a loss of ${graph_min}" elif not graph_msg: # used elif not to avoid storing the message repeatedly graph_msg = "Add the env variables for <graph_min> and <graph_max> to include a graph of previous " \ "week's trend." lost = round(fsum(loss_total), 2) gained = round(fsum(profit_total), 2) port_msg += f'The below values will differ from overall profit/loss if shares were purchased ' \ f'with different price values.\nTotal Profit: ${gained}\nTotal Loss: ${lost}\n' net_worth = round(float(rh.equity()), 2) output = f'Total number of stocks purchased: {n}\n' output += f'Total number of shares owned: {n_}\n\n' output += f'Current value of your total investment is: ${net_worth}\n' total_buy = round(fsum(shares_total), 2) output += f'Value of your total investment while purchase is: ${total_buy}\n' total_diff = round(float(net_worth - total_buy), 2) if total_diff < 0: output += f'Overall Loss: ${total_diff}' else: output += f'Overall Profit: ${total_diff}' yesterday_close = round(float(rh.equity_previous_close()), 2) two_day_diff = round(float(net_worth - yesterday_close), 2) output += f"\n\nYesterday's closing value: ${yesterday_close}" if two_day_diff < 0: output += f"\nCurrent Dip: ${two_day_diff}" else: output += f"\nCurrent Spike: ${two_day_diff}" if not graph_msg: # if graph_msg was not set above graph_msg = f"You have not lost more than ${graph_min} or gained more than " \ f"${graph_max} to generate a graph." return port_msg, profit_output, loss_output, output, graph_msg
# Log in to Robinhood app (will prompt for two-factor) rh = Robinhood() rh.login(username=config.USERNAME, password=config.PASSWORD, qr_code=config.MFA) # STOCK TICKER stock_ticker = input("Enter Stock ticker you would like to trade: ").upper() # Create a User and set the day trade limit. number_of_trades = database_function.get_number_of_trades("database.txt") user = User(0,0,0,0,int(number_of_trades),None) # Get quote data from RH API day_year_quotes = rh.get_historical_quotes(stock_ticker, 'day', 'year') #print(* day_year_quotes["results"][0]["historicals"], sep='\n') async def run(): while True: time_string = time.strftime("%m/%d/%Y, %H:%M:%S", time.localtime()) # POST TIME print("\nGetting historical quotes on {}".format(time_string)) # This gets the last 60 days including today. five_min_day_yahoo = yahoo_finance.get_stock_history(stock_ticker, "5m") # Create list of closing prices from RH API close_prices = [] [close_prices.append(float(key['close_price'])) for key in day_year_quotes["results"][0]["historicals"]]