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)))
print('portfolioValue =', portfolioValue) #allocate portfolio spyAllocationPercentage = calcAlloc(rh) tltAllocationPercentage = 1 - spyAllocationPercentage print('spyAllocationPercentage = ', spyAllocationPercentage) print('tltAllocationPercentage = ', tltAllocationPercentage) spyTargetAllocation = spyAllocationPercentage * portfolioValue tltTargetAllocation = tltAllocationPercentage * portfolioValue print('spyTargetAllocation = ', spyTargetAllocation) print('tltTargetAllocation = ', 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) print('spyBidPrice = ', 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) print('tltBidPrice = ', tltBidPrice) #recommend position sizes
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