def sell_old_stocks(): divies = [[x.get('instrument'), x.get('record_date')] for x in r.get_dividends()] positions_data = r.get_current_positions() for position in positions_data: for d in divies: if position.get('instrument') in d[0]: about = r.request_get(position['instrument']) div_diff = (datetime.strptime(d[1], '%Y-%m-%d') - today).days if div_diff <= 0: stock_dict = r.stocks.get_stock_quote_by_symbol(about.get('symbol')) last_trade_price = float(stock_dict.get('last_trade_price')) if last_trade_price / float(position['average_buy_price']) > 1.005: if float(position.get('shares_held_for_sells')) == 0: if easygui.ccbox(msg=about.get('symbol') + '\n' + d[1] + '\nQuantity: ' + str(position['quantity']) + '\nPurchase $' + str(float(position['average_buy_price'])) + '\nCurrent price $' + str(last_trade_price) + '\nProfit per $' + str(float(last_trade_price) - float(position['average_buy_price'])) + '\nTotal win $' + str((float(last_trade_price) - float(position['average_buy_price']))*float(position['quantity'])) + '\nROI ' + str(100 - (float(last_trade_price) / float(position['average_buy_price']))*-100) + '%' ): r.order_sell_limit(about.get('symbol'), position['quantity'], round(last_trade_price*1.0035, 2)) print('selling ', about.get('symbol')) else: stock_dict = r.stocks.get_stock_quote_by_symbol(about.get('symbol')) last_trade_price = float(stock_dict.get('last_trade_price')) if last_trade_price / float(position['average_buy_price']) > 1.015: if float(position.get('shares_held_for_sells')) == 0: if easygui.ccbox(msg='NO DIVVIE SALE\n' +about.get('symbol') + '\n' + d[1] + '\nQuantity: ' + str(position['quantity']) + '\nPurchase $' + str(float(position['average_buy_price'])) + '\nCurrent price $' + str(last_trade_price) + '\nProfit per $' + str(float(last_trade_price) - float(position['average_buy_price'])) + '\nTotal win $' + str((float(last_trade_price) - float(position['average_buy_price'])) * float(position['quantity'])) + '\nROI ' + str(100 - (float(last_trade_price) / float(position['average_buy_price'])) * -100) + '%'): r.order_sell_limit(about.get('symbol'), position['quantity'], round(last_trade_price * 1.0035, 2)) print('selling ', about.get('symbol'))
def rh_profit_and_loss(username=None, password=None, starting_allocation=5000, start_date=None, end_date=None, csv_export=1, buy_and_hold=0, pickle=0, options=1): # from rmccorm4 Robinhood-Scraper class Order: def __init__(self, side, symbol, shares, price, date, state): self.side = side self.symbol = symbol self.shares = float(shares) self.price = float(price) self.date = date self.state = state def pl(self): if self.side == 'buy': return -1 * int(self.shares) * float(self.price) else: return int(self.shares) * float(self.price) class Stock: def __init__(self, symbol): self.symbol = symbol self.orders = [] self.net_shares = 0 self.net_pl = 0 def itemize_stocks(): # Create list for each stock stocks = {} with open('orders.csv', 'r') as csvfile: lines = csv.reader(csvfile, delimiter=',') for line in lines: ticker = line[1] price = line[3] # Check for header or invalid entries if ticker == 'symbol' or price == '': continue # Add stock to dict if not already in there if ticker not in stocks: stocks[ticker] = Stock(ticker) # Add order to stock stocks[ticker].orders.append( Order(line[0], line[1], line[2], line[3], line[4], line[5])) return stocks def calculate_itemized_pl(stocks): for stock in stocks.values(): for order in stock.orders: if order.side == 'buy': stock.net_shares += order.shares else: stock.net_shares -= order.shares # order.pl() is positive for selling and negative for buying stock.net_pl += order.pl() # Handle outstanding shares - should be current positions if stock.net_shares > 0: requestResponse = requests.get( "https://sandbox.iexapis.com/stable/stock/{}/price?token={}" .format(stock.symbol.lower(), os.environ.get('IEX_TOKEN'))) # requestResponse = requests.get("https://api.iextrading.com/1.0/stock/{}/price".format(stock.symbol.lower())) json = requestResponse.json() last_price = float(json) # Add currently held shares from net_pl as if selling now (unrealized PnL) stock.net_pl += stock.net_shares * last_price # Should handle free gift stocks elif stock.net_shares < 0: stock.symbol += ' ' # INSTANTIATE ROBINHOOD auth_information # auth_information = r.login(username, password) print(auth_information) # optionorders = df_options_orders_history # Retrieve options history start_date == 'January 1, 2020' options_pnl = 0 if options == 1: df_options_orders_history = rh.get_all_history_options_orders(r) df_options_orders_history.to_csv('options_orders_history_df.csv') if pickle == 1: df_options_orders_history.to_pickle('df_options_orders_history') options_pnl = df_options_orders_history[start_date:end_date][ 'value'].sum() print( "*************FILE EXPORTED ******************************\n options_orders_history_df.csv\n\n" ) print("OPTIONS PROFIT OR LOSS :") print(options_pnl) open_options = r.get_all_open_option_orders() for i in open_options: print(i) df_order_history, _ = rh.get_order_history(r) df_orders = df_order_history[[ 'side', 'symbol', 'shares', 'avg_price', 'date', 'state' ]] df_orders.columns = ['side', 'symbol', 'shares', 'price', 'date', 'state'] # Filter for input dates df_orders['date'] = pd.to_datetime(df_orders['date']) df_orders = df_orders.sort_values('date') df_orders = df_orders.set_index('date') df_orders = df_orders[start_date:end_date] df_orders['date'] = df_orders.index if pickle == 1: df_orders.to_pickle('df_orders_history') if start_date == 'January 1, 2012': start_date = df_orders.iloc[0]['date'].strftime('%B %d, %Y') df_orders.set_index('side').to_csv('orders.csv', header=None) stocks = itemize_stocks() calculate_itemized_pl(stocks) with open('stockwise_pl.csv', 'w') as outfile: writer = csv.writer(outfile, delimiter=',') writer.writerow(['SYMBOL', 'net_pnl', 'n_trades']) sorted_pl = sorted(stocks.values(), key=operator.attrgetter('net_pl'), reverse=True) total_pl = 0 total_trades = 0 for stock in sorted_pl: num_trades = len(stock.orders) writer.writerow([ stock.symbol, '{0:.2f}'.format(stock.net_pl), len(stock.orders) ]) total_pl += stock.net_pl total_trades += num_trades writer.writerow(['Totals', total_pl, total_trades]) # print('Created', outfile.name, 'in this directory.') # Read the pnl we generated df_pnl = pd.read_csv('stockwise_pl.csv') # Get dividends from Robinhood dividends = r.get_dividends() # Put the dividends in a dataframe list_of_records = [] for each in dividends: list_of_records.append(pd.DataFrame(pd.Series(each)).T) df_dividends = pd.concat(list_of_records) df_dividends = df_dividends.set_index('id') df_dividends['id'] = df_dividends.index # Load in our pickled database of instrument-url lookups instruments_df = pd.read_pickle('symbol_and_instrument_urls') df_dividends['ticker'] = np.nan for each in df_dividends.itertuples(): symbol, instruments_df = rh.get_symbol_from_instrument_url( each.instrument, instruments_df) df_dividends.loc[each.id, 'ticker'] = symbol if pickle == 1: df_dividends.to_pickle('df_dividends') if csv_export == 1: df_dividends.to_csv('divs_raw.csv') # df_pnl.to_csv('pnl.csv') # Filter df_dividends df_dividends['record_date'] = pd.to_datetime(df_dividends['record_date']) df_dividends = df_dividends.sort_values('record_date') df_dividends = df_dividends.set_index('record_date') df_dividends = df_dividends[start_date:end_date] # convert numbers to actual numbers df_dividends['amount'] = pd.to_numeric(df_dividends['amount']) # Group dividend payouts by ticker and sum df_divs_summed = df_dividends.groupby('ticker').sum() # Set a column to the ticker df_divs_summed['ticker'] = df_divs_summed.index # For the stockwise pnl, set index to the ticker ('SYMBOL') df_pnl = df_pnl.set_index('SYMBOL') try: df_pnl = df_pnl.drop('Totals') except KeyError as e: print("Totals row not found") # Set div payouts column df_pnl['div_payouts'] = np.nan # For each in the summed for each in df_divs_summed.itertuples(): amount = each.amount df_pnl.loc[each.ticker, 'div_payouts'] = amount if pickle == 1: df_divs_summed.to_pickle('df_divs_summed') df_pnl.to_pickle('df_pnl') if csv_export == 1: # df_divs_summed.to_csv('divs_summed_df.csv') df_pnl.to_csv('pnl_df.csv') # Calculate the dividends received (or that are confirmed you will receive in the future) dividends_paid = float(df_pnl.sum()['div_payouts']) # Calculate the total pnl pnl = float(df_pnl.sum()['net_pnl']) if buy_and_hold == 1: # Get historical price of QQQ requestResponse = requests.get( "https://api.iextrading.com/1.0/stock/qqq/chart/5y") json = requestResponse.json() df_qqq = pd.DataFrame(json) df_qqq.index = pd.to_datetime(df_qqq['date']) # If the date is older than we can get from IEX, load the historical data if pd.to_datetime(start_date) < df_qqq.iloc[0].name: df_QQQ_history = pd.read_pickle('data/QQQ_close') QQQ_starting_price = float(df_QQQ_history.iloc[0]['close']) else: df_qqq = df_qqq[start_date:end_date] QQQ_starting_price = float(df_qqq.iloc[0]['close']) # Filter the dataframe for start and end date df_qqq = df_qqq[start_date:end_date] # Set end price of the trading period QQQ_ending_price = float(df_qqq.iloc[-1]['close']) # Calculate the buy-and-hold value QQQ_buy_and_hold_gain = starting_allocation * ( QQQ_ending_price - QQQ_starting_price) / QQQ_starting_price # When printing the final output, if no date was provided, print "today" if end_date == 'January 1, 2030': end_date_string = 'today' else: end_date_string = end_date # Retrieve options history options_pnl = 0 if options == 1: df_options_orders_history = rh.get_all_history_options_orders(r) if csv_export == 1: df_options_orders_history.to_csv('options_orders_history_df.csv') if pickle == 1: df_options_orders_history.to_pickle('df_options_orders_history') options_pnl = df_options_orders_history[start_date:end_date][ 'value'].sum() total_pnl = round(pnl + dividends_paid + options_pnl, 2) # Print final output print("~~~") print("From {} to {}, your total Profit/Loss is ${}".format( start_date, end_date_string, total_pnl)) print( "You've made ${} buying and selling individual equities, received ${} in dividends, and ${} on options trades" .format(round(pnl, 2), round(dividends_paid, 2), round(options_pnl, 2))) # Calculate ROI, if the user input a starting allocation if roi == 1: return_on_investment = round((total_pnl / starting_allocation) * 100, 2) print("Your return-on-investment (ROI) is: %{}".format( return_on_investment)) if buy_and_hold == 1: print( "With a starting allocation of ${}, if you had just bought and held QQQ, your PnL would be ${}" .format(starting_allocation, round(QQQ_buy_and_hold_gain, 2))) print("~~~") # Delete the csv we were processing earlier os.remove('stockwise_pl.csv')
def import_portfolio_robinhood(access_token, username=None, password=None, name="Robinhood", free_stock=False): """ Accesses Robinhood account and downloads transactions Parameters ========== username : Robinhood username password : Robinhood account password name : desired portfolio name free_stock : include a free stock not captured by transaction history (see below) Returns ======= df : dataframe with transactions p : portfolio (Portfolio class object) """ if not access_token: if username is None: username = getpass("Username: "******"Password: "******"Parsing orders ...") # pre-pull all tickers before creating order history df Tickerset = [] for order in orders: if len(order["executions"]): Tickerset.append(order["instrument"]) Tickerset = list(set(Tickerset)) # make a lookup dict for ticker symbols Tickersymbols = {} for element in Tickerset: Tickersymbols[element] = r.get_instrument_by_url(element)["symbol"] for order in orders: if len(order["executions"]): Date.append(pd.to_datetime(order["last_transaction_at"])) Transaction.append(order["side"]) Ticker.append(Tickersymbols[order["instrument"]]) Currency.append("USD") Price.append(order["average_price"]) Quantity.append(order["quantity"]) # add deposits transfers = r.get_bank_transfers() print("Parsing bank transfers ...") for transfer in transfers: if transfer["cancel"] is None: Date.append(pd.to_datetime(transfer["created_at"])) Transaction.append(transfer["direction"]) Ticker.append(None) Currency.append("USD") Price.append(1.0) Quantity.append(transfer["amount"]) # add dividends dividends = r.get_dividends() print("Parsing dividends ...") for dividend in dividends: if dividend["state"] == "paid": Date.append(pd.to_datetime(dividend["paid_at"])) Transaction.append("dividend") Ticker.append(Tickersymbols[dividend["instrument"]]) Currency.append("USD") Price.append(1.0) Quantity.append(dividend["amount"]) if free_stock == True: # include free stock (Robinhood promotion, not included in transaction history) print("Adding promotional stock ...") Date.append(pd.to_datetime("2/1/18")) Transaction.append("buy") Ticker.append("CHK") Currency.append("USD") Price.append(0.0) Quantity.append(1.0) # build dataframe d = { "Date": Date, "Transaction": Transaction, "Ticker": Ticker, "Currency": Currency, "Price": pd.to_numeric(Price), "Quantity": pd.to_numeric(Quantity), } df = pd.DataFrame(data=d) # strip time of day information df.Date = df.Date.map(lambda x: x.strftime("%m-%d-%Y")) df.Date = pd.to_datetime(df.Date) # create a new portfolio object p = Portfolio(name=name) # parse p = parse_portfolio(df, p) return p
def test_dividends(self): stock = r.get_dividends(info=None) self.assertNotEqual(len(stock), 0)
def import_portfolio_robinhood(username=None, password=None, name="Robinhood", free_stock=False): """ Accesses Robinhood account and downloads transactions Parameters ========== username : Robinhood username password : Robinhood account password name : desired portfolio name free_stock : include a free stock not captured by transaction history (see below) Returns ======= df : dataframe with transactions p : portfolio (Portfolio class object) """ import robin_stocks as r from getpass import getpass if username is None: username = getpass("Username: "******"Password: "******"Parsing orders ...") for order in orders: if len(order['executions']): Date.append(pd.to_datetime(order['last_transaction_at'])) Transaction.append(order['side']) Ticker.append( r.get_instrument_by_url(order['instrument'])['symbol']) Currency.append('USD') Price.append(order['average_price']) Quantity.append(order['quantity']) # add deposits transfers = r.get_bank_transfers() print("Parsing bank transfers ...") for transfer in transfers: if transfer['cancel'] is None: Date.append(pd.to_datetime(transfer['created_at'])) Transaction.append('deposit') Ticker.append(None) Currency.append('USD') Price.append(1.0) Quantity.append(transfer['amount']) # add dividends dividends = r.get_dividends() print("Parsing dividends ...") for dividend in dividends: if dividend['state'] == 'paid': Date.append(pd.to_datetime(dividend['paid_at'])) Transaction.append('dividend') Ticker.append( r.get_instrument_by_url(dividend['instrument'])['symbol']) Currency.append('USD') Price.append( float(dividend['amount']) / float(dividend['position'])) Quantity.append(dividend['position']) if free_stock == True: # include free stock (Robinhood promotion, not included in transaction history) print("Adding promotional stock ...") Date.append(pd.to_datetime('2/1/18')) Transaction.append('buy') Ticker.append('CHK') Currency.append('USD') Price.append(0.0) Quantity.append(1.0) # build dataframe d = { 'Date': Date, 'Transaction': Transaction, 'Ticker': Ticker, 'Currency': Currency, 'Price': pd.to_numeric(Price), 'Quantity': pd.to_numeric(Quantity) } df = pd.DataFrame(data=d) # strip time of day information df.Date = df.Date.map(lambda x: x.strftime('%m-%d-%Y')) df.Date = pd.to_datetime(df.Date) # create a new portfolio object p = Portfolio(name=name) # parse p = parse_portfolio(df, p) return p
def getDividends(self): return self.masterFormat(robin_stocks.get_dividends(), "dividend")
def LOAD_DIVIDENDS(): func=r.get_dividends() return func