def test_crypto_quote(self): crypto = r.get_crypto_quote(self.bitcoin, info=None) self.assertIn('ask_price', crypto) self.assertIn('bid_price', crypto) self.assertIn('mark_price', crypto) self.assertIn('high_price', crypto) self.assertIn('low_price', crypto) self.assertIn('open_price', crypto) self.assertIn('symbol', crypto) self.assertIn('id', crypto) self.assertIn('volume', crypto) crypto = r.get_crypto_quote(self.stock, info=None) self.assertEqual(crypto, None) crypto = r.get_crypto_quote(self.fake, info=None) self.assertEqual(crypto, None)
def test_crypto_quote(self): crypto = r.get_crypto_quote(self.bitcoin, info=None) assert ('ask_price' in crypto) assert ('bid_price' in crypto) assert ('mark_price' in crypto) assert ('high_price' in crypto) assert ('low_price' in crypto) assert ('open_price' in crypto) assert ('symbol' in crypto) assert ('id' in crypto) assert ('volume' in crypto) crypto = r.get_crypto_quote(self.stock, info=None) assert (crypto == None) crypto = r.get_crypto_quote(self.fake, info=None) assert (crypto == None)
def getCurrentPrice(self): try: result = r.get_crypto_quote(self.coin.name) except: print("Problem retrieving crypto quote") return return float(result['mark_price'])
def buy_doge(amount): ui.success(f'Ordering ${amount} of DOGE....\n') # Doge error workaround price = float(rh.get_crypto_quote('DOGE').get('ask_price')) shares = round(amount/price, 0) result = rh.order_buy_crypto_by_quantity('DOGE', shares) ui.chec_ref(result)
def buy(self, ticker): if self.available_cash == 0 or self.available_cash < config[ 'buy_amount_per_trade'] or self.is_trading_locked: return False # Retrieve the actual ask price from Robinhood if not config['simulate_api_calls']: try: quote = rh.get_crypto_quote(ticker) price = float(quote['ask_price']) except: print( 'Could not retrieve ask price from Robinhood. Using Kraken\'s.' ) price = self.data.iloc[-1][ticker] else: price = self.data.iloc[-1][ticker] # Values need to be specified to no more precision than listed in min_price_increments. # Truncate to 7 decimal places to avoid floating point problems way out at the precision limit price_precision = round( floor(price / self.min_price_increments[ticker]) * self.min_price_increments[ticker], 7) # How much to buy depends on the configuration quantity = (self.available_cash if (config['buy_amount_per_trade'] == 0) else config['buy_amount_per_trade']) / price_precision quantity = round( floor(quantity / self.min_share_increments[ticker]) * self.min_share_increments[ticker], 7) if config['trades_enabled'] and not config['simulate_api_calls']: try: buy_info = rh.order_buy_crypto_limit(str(ticker), quantity, price_precision) # Add this new asset to our orders self.orders[buy_info['id']] = asset(ticker, quantity, price_precision, buy_info['id'], 'PB') print('## Submitted order to buy ' + str(quantity) + ' ' + str(ticker) + ' at $' + str(price_precision)) if (price != self.data.iloc[-1][ticker]): print('## Price Difference: Kraken $' + str(self.data.iloc[-1][ticker]) + ', Robinhood $ ' + str(price)) except: print('An exception occurred while trying to buy.') return False else: print('## Would have bought ' + str(ticker) + ' ' + str(quantity) + ' at $' + str(price_precision) + ', if trades were enabled') return False return True
def sell(self, asset): # Do we have enough of this asset to sell? if self.is_trading_locked: return False # Retrieve the actual bid price from Robinhood if not config['simulate_api_calls']: try: quote = rh.get_crypto_quote(asset.ticker) price = float(quote['bid_price']) except: print( 'Could not retrieve bid price from Robinhood. Using Kraken\'s.' ) price = self.data.iloc[-1][asset.ticker] else: price = self.data.iloc[-1][asset.ticker] # Values needs to be specified to no more precision than listed in min_price_increments. # Truncate to 7 decimal places to avoid floating point problems way out at the precision limit price_precision = round( floor(price / self.min_price_increments[asset.ticker]) * self.min_price_increments[asset.ticker], 7) profit = round((asset.quantity * price_precision) - (asset.quantity * asset.price), 3) if config['trades_enabled'] and not config['simulate_api_calls']: try: sell_info = rh.order_sell_crypto_limit(str(asset.ticker), asset.quantity, price_precision) # Mark this asset as pending sold self.orders[asset.order_id].status = 'PS' self.orders[asset.order_id].profit = profit print('## Submitted order to sell ' + str(asset.quantity) + ' ' + str(asset.ticker) + ' at $' + str(price_precision) + ' (estimated profit: $' + str(profit) + ')') if (price != self.data.iloc[-1][asset.ticker]): print('## Price Difference: Kraken $' + str(self.data.iloc[-1][asset.ticker]) + ', Robinhood $ ' + str(price)) except: print('An exception occurred while trying to sell.') return False else: print('## Would have sold ' + str(asset.ticker) + ' ' + str(asset.quantity) + ' at $' + str(price_precision) + ', if trades were enabled') return False return True
def check_cash_on_hand(self, symbol="USD"): cash_on_hand = 0 if symbol == "USD": info = rh.load_phoenix_account() if info is None: raise ConnectionError cash_on_hand = float(info['account_buying_power']['amount']) # TODO: # If we want to separate this bot from the rest of the acct, then we will need to # do other calculations here based on orders placed and total amount willing to invest. # If we're fine using the entire account balance for this bot, then we only need # to return the account_buying_power. else: crypto_on_hand = dict() crypto_positions = rh.get_crypto_positions() if crypto_positions is None: raise ConnectionError if symbol not in self.ndigits.keys(): self.ndigits[symbol] = float_to_ndigits( float( list( filter(lambda x: x['currency']['code'] == symbol, crypto_positions))[0]['currency'] ['increment'])) self.ndigits[symbol] = min(8, self.ndigits[symbol]) try: crypto_on_hand['cost'] = float( list( filter(lambda x: x['currency']['code'] == symbol, crypto_positions))[0]['cost_bases'][0] ['direct_cost_basis']) except IndexError: crypto_on_hand['cost'] = 0 try: crypto_on_hand['quantity'] = float( list( filter(lambda x: x['currency']['code'] == symbol, crypto_positions))[0]['quantity']) except IndexError: crypto_on_hand['quantity'] = 0 get_quote = rh.get_crypto_quote(symbol) crypto_on_hand['bid_price'] = float(get_quote['bid_price']) crypto_on_hand['ask_price'] = float(get_quote['ask_price']) crypto_on_hand['quote'] = float(get_quote['bid_price']) crypto_on_hand[ 'value'] = crypto_on_hand['quote'] * crypto_on_hand['quantity'] cash_on_hand = crypto_on_hand return cash_on_hand
def update_max_min(cryptos): print_str = '' for crypto in cryptos: crypto['current_price'] = round( float(rs.get_crypto_quote(crypto['name'])['ask_price']), 2) # Update max if crypto['current_max'] < crypto['current_price']: crypto['current_max'] = round(crypto['current_price'], 2) # Update min if crypto['current_min'] > crypto['current_price']: crypto['current_min'] = round(crypto['current_price'], 2) print_str += f"[{bcolors.WARNING}{crypto['name']}{bcolors.ENDC}: Current: {bcolors.OKGREEN}{crypto['current_price']}{bcolors.ENDC}, Max: {bcolors.OKBLUE}{crypto['current_max']}{bcolors.ENDC}, Min: {bcolors.FAIL}{crypto['current_min']}{bcolors.ENDC}]" print(print_str)
def getcryptoquotes( tradingcrypto ): #gets current quotes and stores into 100 most recent value list mp = r.get_crypto_quote(tradingcrypto, 'mark_price') ap = r.get_crypto_quote(tradingcrypto, 'ask_price') bp = r.get_crypto_quote(tradingcrypto, 'bid_price') prices = {'Ask': ap, 'Mark': mp, 'Bid': bp} askavg.append(prices['Ask']) if len(askavg) >= 100: for x in range(0, (len(askavg) - 100)): del askavg[0] markavg.append(prices['Mark']) if len(markavg) >= 100: for x in range(0, (len(markavg) - 100)): del markavg[0] bidavg.append(prices['Bid']) if len(bidavg) >= 100: for x in range(0, (len(bidavg) - 100)): del bidavg[0] return (prices)
def getPrices(self): prices = {} emptyDict = {} for c in self.coinList: try: result = r.get_crypto_quote(c) price = result['mark_price'] except: print('An exception occurred retrieving prices.') return emptyDict prices.update({c: float(price)}) return prices
import robin_stocks as r ''' This is an example script that will show you how to close option positions. ''' #!!! Fill out username and password username = '******' password = '******' #!!! login = r.login(username, password) symbol = 'DOGE' cryptoList = r.get_crypto_quote(symbol) print(cryptoList)
def bid(symbol): #test: works return float(r.get_crypto_quote(symbol)['bid_price'])
def trigger_tx(self, symbol, quantity=None, price=None, side=None, cash_on_hand=None, quantity_on_hand=None, in_dollars=False): """ Attempts to make a trade. Returns None if no trade was made. """ info = None if side not in {"buy", "sell"}: raise Exception("side should be 'buy' or 'sell'") if side == 'buy': if cash_on_hand is None: cash_on_hand = self.check_cash_on_hand(symbol="USD") max_allocation = MAX_ALLOCATION[symbol] if MAX_ALLOCATION_IS_PERCENT: max_allocation = (max_allocation / 100) * self.total_value if cash_on_hand < MIN_DOLLARS_PER_TRADE: return if price is None: raise Exception( "Price cannot be None. Calcuate a price or change the code to calculate a default price." ) if symbol == 'DOGE': price = round(price, 6) else: price = round(price, 2) if quantity is None: # price is not None and quantity is None # so calculate a quantity: buy_amount = min(cash_on_hand, MAX_DOLLARS_PER_BUY[symbol], max_allocation - self.symbol_value[symbol]) if cash_on_hand - buy_amount < MIN_DOLLARS_PER_TRADE: # If buy would leave us with less cash than we can trade with, just use all of it. buy_amount = cash_on_hand quantity = round(buy_amount / price, self.ndigits[symbol]) info = rh.order_buy_crypto_limit(symbol, quantity, price) #if symbol == 'DOGE': # info = rh.order_buy_crypto_by_price(symbol, round(buy_amount, self.ndigits[symbol])) # quantity = round(buy_amount/price , self.ndigits[symbol]) # info = rh.order_buy_crypto_limit(symbol, quantity, price) #else: # #info = rh.order_buy_crypto_by_price(symbol, buy_amount) else: info = rh.order_buy_crypto_limit(symbol, quantity, price) else: # side == 'sell' if price is None: price = float(rh.get_crypto_quote(symbol)['bid_price']) if symbol == 'DOGE': price = round(price, 8) else: price = round(price, 2) if quantity_on_hand is None: quantity_on_hand = self.quantity_on_hand[symbol] # raise Exception("quantity_on_hand cannot be None. Calcuate a quantity or change the code to calculate a default price.") if quantity_on_hand * price < MIN_DOLLARS_PER_TRADE: return if in_dollars: info = rh.order_sell_crypto_by_price(symbol, quantity) else: if quantity is None: if in_dollars: raise NotImplementedError quantity = round(MAX_DOLLARS_PER_SELL[symbol] / price, self.ndigits[symbol]) if price * quantity_on_hand < MAX_DOLLARS_PER_SELL[ symbol] or price * (quantity_on_hand - quantity ) < MIN_DOLLARS_PER_TRADE: quantity = quantity_on_hand else: pass info = rh.order_sell_crypto_by_quantity(symbol, quantity) retval = info if info is not None: if 'account_id' in info.keys(): self.disp_warn_feed.feedlines( f"{side.capitalize()}ing: {quantity} {symbol.upper()} at limit price ${price}" ) with Capturing() as output: print( f"Trade executed: symbol = {symbol}, quantity = {quantity}, price = {price}, side = {side}\n" ) print(info) try: self.order_ids[time.time()] = info['id'] # self.bump_rsi(symbol,side) except KeyError: retval = None logging.info(output) return retval
def get_new_data(self, now): # If the current dataset has gaps in it, we refresh it from Kraken if self.data_has_gaps(now): self.init_data() new_row = {'timestamp': now.strftime("%Y-%m-%d %H:%M")} # Calculate moving averages and RSI values for a_kraken_ticker, a_robinhood_ticker in config['ticker_list'].items( ): if not config['simulate_api_calls']: if config['data_source'] == 'kraken': try: result = get_json( 'https://api.kraken.com/0/public/Ticker?pair=' + str(a_kraken_ticker)).json() if len(result['error']) == 0: new_row[a_robinhood_ticker] = round( float( result['result'][a_kraken_ticker]['a'][0]), 3) except: print( 'An exception occurred retrieving prices from Kraken.' ) return False else: try: result = rh.get_crypto_quote(a_robinhood_ticker) new_row[a_robinhood_ticker] = round( float(result['mark_price']), 3) except: print( 'An exception occurred retrieving prices from Robinhood.' ) return False else: new_row[a_robinhood_ticker] = round( float(randint(400000, 500000)), 3) # If the new price is more than 40% lower/higher than the previous reading, assume it's an error somewhere percent_diff = (abs(new_row[a_robinhood_ticker] - self.data.iloc[-1][a_robinhood_ticker]) / self.data.iloc[-1][a_robinhood_ticker]) * 100 if percent_diff > 30: print('Error: new price ($' + str(new_row[a_robinhood_ticker]) + ') differs ' + str(round(percent_diff, 2)) + '% from previous value, ignoring.') return False self.data = self.data.append(new_row, ignore_index=True) # If the API is overloaded, it keeps returning the same value if (self.data.tail(4)[a_robinhood_ticker].to_numpy()[-1] == self.data.tail(4)[a_robinhood_ticker].to_numpy()).all(): print('Repeating values detected for ' + str(a_robinhood_ticker) + '. Ignoring data point.') self.data = self.data[:-1] elif self.data.shape[0] > 0: self.data[a_robinhood_ticker + '_SMA_F'] = self.data[a_robinhood_ticker].rolling( window=config['moving_average_periods'] ['sma_fast']).mean() self.data[a_robinhood_ticker + '_SMA_S'] = self.data[a_robinhood_ticker].rolling( window=config['moving_average_periods'] ['sma_slow']).mean() self.data[a_robinhood_ticker + '_SMA_S'] = self.data[a_robinhood_ticker].rolling( window=config['moving_average_periods'] ['sma_slow']).mean() self.data[ a_robinhood_ticker + '_EMA_F'] = self.data[a_robinhood_ticker].ewm( span=config['moving_average_periods']['ema_fast'], adjust=False, min_periods=config['moving_average_periods'] ['ema_fast']).mean() self.data[ a_robinhood_ticker + '_EMA_S'] = self.data[a_robinhood_ticker].ewm( span=config['moving_average_periods']['ema_slow'], adjust=False, min_periods=config['moving_average_periods'] ['ema_slow']).mean() self.data[a_robinhood_ticker + '_RSI'] = RSI( self.data[a_robinhood_ticker].values, timeperiod=config['rsi_period']) self.data[a_robinhood_ticker + '_MACD'], self.data[ a_robinhood_ticker + '_MACD_S'], macd_hist = MACD( self.data[a_robinhood_ticker].values, fastperiod=config['moving_average_periods'] ['macd_fast'], slowperiod=config['moving_average_periods'] ['macd_slow'], signalperiod=config['moving_average_periods'] ['macd_signal']) if config['save_charts'] == True: self.save_chart([ a_robinhood_ticker, str(a_robinhood_ticker) + '_SMA_F', str(a_robinhood_ticker) + '_SMA_S' ], str(a_robinhood_ticker) + '_sma') self.save_chart([ a_robinhood_ticker, str(a_robinhood_ticker) + '_EMA_F', str(a_robinhood_ticker) + '_EMA_S' ], str(a_robinhood_ticker) + '_ema') self.save_chart_rescale( [a_robinhood_ticker, str(a_robinhood_ticker) + '_RSI'], str(a_robinhood_ticker) + '_rsi') self.save_chart_rescale([ a_robinhood_ticker, str(a_robinhood_ticker) + '_MACD', str(a_robinhood_ticker) + '_MACD_S' ], str(a_robinhood_ticker) + '_macd') return True
def QUOTE_CRYPTO(symbol): ans=r.get_crypto_quote(symbol) return float(ans["ask_price"])
def get_market_value(self): login = r.login(self.username, self.password) btc_info = r.get_crypto_quote('BTC') login = r.logout() return btc_info['mark_price']
def crypto_quote(symbol): result = rh.get_crypto_quote(symbol) ui.success(result)
def getcryptoquotes(tradingcrypto): #gets current quotes and stores into 100 most recent value list mp=r.get_crypto_quote(tradingcrypto,'mark_price') ap=r.get_crypto_quote(tradingcrypto,'ask_price') bp=r.get_crypto_quote(tradingcrypto,'bid_price') prices = {'Ask':ap,'Mark':mp,'Bid':bp} return(prices)
def get_crypto_price(symbol): price_data = r.get_crypto_quote(symbol) return Decimal(price_data['mark_price'])
def ask(symbol): #test: works return float(r.get_crypto_quote(symbol)['ask_price'])