def __init__(self, endpoint, key, config): self.config = config self.api = QtradeAPI(endpoint, key=key) self.prev_alloc_profile = None self.market_configs = { ms: MarketConfig(ms, mkt, default=config['markets'].get('default')) for ms, mkt in config['markets'].items() if ms != 'default' }
def exchange_credentials(exchange): if exchange == 'qTrade': while True: credentials = {exchange: {'api_key': str(input('Input Your qTrade API Key'+'\n'+'> '))}} client = QtradeAPI('https://api.qtrade.io', key=credentials[exchange]['api_key']) try: client.get("/v1/user/me") except: print('Invalid Credentials'+'\n') continue else: print('qTrade Credentials Verified'+'\n') break elif exchange == 'Bybit': while True: credentials = {exchange: {'api_key': str(input('Input Your Bybit API Key'+'\n'+'> ')), 'api_secret': str(input('Input Your Bybit API Secret'+'\n'+'> '))}} client = bybit(test=False,api_key=credentials[exchange]['api_key'], api_secret=credentials[exchange]['api_secret']) resp = client.APIkey.APIkey_info().result()[0]['ret_msg']; if resp == 'invalid api_key': print('Invalid Credentials'+'\n') continue else: print('Bybit Credentials Verified'+'\n') break elif exchange == 'Bitmex': while True: credentials = {exchange: {'api_key': str(input('Input Your Bitmex API Key'+'\n'+'> ')), 'api_secret': str(input('Input Your Bitmex API Secret'+'\n'+'> '))}} client = bitmex(test=False,api_key=credentials[exchange]['api_key'], api_secret=credentials[exchange]['api_secret']); try: print('\n'+'Testing Bitmex Credentials'+'\n') client.User.User_getWalletHistory().result(); except bravado.exception.HTTPError: print('Invalid Credentials'+'\n') continue else: print('Bitmex Credentials Verified'+'\n') break return credentials
def load_credentials(exchange, bot): credentials = json_read('credentials')[exchange] if exchange == 'Bitmex': client = bitmex(test=False,api_key=credentials['api_key'],api_secret=credentials['api_secret']) elif exchange == 'Bybit': client = bybit(test=False,api_key=credentials['api_key'],api_secret=credentials['api_secret']) elif exchange == 'qTrade': client = QtradeAPI('https://client.qtrade.io', key=credentials['api_key']) if bot == True: bot = (credentials['bot_token'], credentials['bot_chatID']) return client, bot
def cli(ctx, config, endpoint, keyfile, verbose): log_level = "DEBUG" if verbose is True else "INFO" root = log.getLogger() root.setLevel(log_level) handler = log.StreamHandler(sys.stdout) handler.setLevel(log_level) formatter = log.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) root.addHandler(handler) api = QtradeAPI(endpoint, key=keyfile.read().strip()) config = yaml.load(config) ctx.obj['mdc'] = MarketDataCollector(config['market_data_collector']) ctx.obj['obm'] = OrderbookManager(api, config['orderbook_manager'])
class QTradeScraper(APIScraper): def __init__(self, **kwargs): self.api = QtradeAPI("https://api.qtrade.io", key=open("lpbot_hmac.txt", "r").read().strip()) super().__init__(**kwargs) def scrape_ticker(self): tickers = {} for market, qmarket in self.markets.items(): res = self.api.get("/v1/ticker/{}".format(market)) log.debug("Ticker %s from %s was acquired successfully", market, self.exchange_name) bid = Decimal(res["bid"]).quantize(COIN) log.debug("Bid price is %s", bid) last = Decimal(res["last"]).quantize(COIN) log.debug("Last price is %s", last) ask = Decimal(res["ask"]).quantize(COIN) log.debug("Ask price is %s", ask) tickers[qmarket] = {"bid": bid, "last": last, "ask": ask} return tickers
log.warning(f"day_volume_base: {'%.8f' % pair_market.day_volume_base}") log.warning(f"day_volume_market: {'%.8f' % pair_market.day_volume_market}") log.warning(f"id: {pair_market.id}") log.warning(f"id_hr: {pair_market.id_hr}") log.warning(f"last_price: {'%.8f' % pair_market.last_price}") log.warning(f"day_spread: {'%.8f' % pair_market.day_spread}") log.warning(f"spread_pct: {'%.8f' % pair_market.spread_pct}") if __name__ == "__main__": # Create a session object to make repeated API calls easy! api = requests.Session() # Create an authenticator with your API key api.auth_native = QtradeAPI("https://api.qtrade.io", key=load_credentials()) # use in the future api.auth = QtradeAuth(load_credentials()) # load currencies active_currencies = [] with open("config.json") as confile: confile_contents = json.loads(confile.read()) for currency in confile_contents: log.warning(f"Loaded {currency}") active_currencies.append( Config( name=currency["name"], sell_amount=currency["sell_amount"], buy_amount=currency["buy_amount"],
from qtrade_client.api import QtradeAPI import json def scrape_trades(api): trades = api.get('/v1/user/trades')["trades"] while True: new_trades = api.get('/v1/user/trades', newer_than=trades[-1]["id"])["trades"] if len(new_trades) == 0: break trades += new_trades return trades if __name__ == "__main__": hmac = open("lpbot_hmac.txt").read().strip() api = QtradeAPI("https://api.qtrade.io", key=hmac) trades = scrape_trades(api) f = open("trades.json", "w") f.write(json.dumps(trades)) f.close()
from qtrade_client.api import QtradeAPI # Create an API client with your key endpoint = "https://api.qtrade.io" key = "1:1111111111111111111111111111111111111111111111111111111111111111" api = QtradeAPI(endpoint, key) # Make a call to API res = api.orders(open=True) print(res) # Returned list: [{'created_at': '2019-11-12T22:42:15.643486Z', 'id': 8932525, 'market_amount': '1.10428011', 'market_amount_remaining': '1.10428011', 'market_id': 1, 'open': True, 'order_type': 'sell_limit', 'price': '0.0083759', 'trades': None}, {'created_at': '2019-11-12T22:42:14.713136Z', 'id': 8932523, 'market_amount': '0.92023342', 'market_amount_remaining': '0.92023342', 'market_id': 1, 'open': True, 'order_type': 'sell_limit', 'price': '0.00788731', 'trades': None}, {'base_amount': '0.00433166',
def verify_credentials(exchange, bot): try: credentials = load_file(exchange + '_credentials') except FileNotFoundError: print('Creating ' + exchange + ' Credentials File' + '\n') while True: credentials = { 'exchange': exchange, 'api_key': str(input('Input Your ' + exchange + ' API Key' + '\n' + '> ')) } if exchange != 'qTrade': credentials.update({ 'api_secret': str( input('Input Your ' + exchange + ' API Secret' + '\n' + '> ')) }) if exchange == 'Bitmex': client = bitmex(test=False, api_key=credentials['api_key'], api_secret=credentials['api_secret']) try: print('\n' + 'Testing Bitmex Credentials' + '\n') client.User.User_getWalletHistory().result() except bravado.exception.HTTPError: print('Invalid Credentials' + '\n') continue else: print('Bitmex Credentials Verified' + '\n') break elif exchange == 'Bybit': client = bybit(test=False, api_key=credentials['api_key'], api_secret=credentials['api_secret']) resp = client.APIkey.APIkey_info().result()[0]['ret_msg'] if resp == 'invalid api_key': print('Invalid Credentials' + '\n') continue else: print('Bybit Credentials Verified' + '\n') break elif exchange == 'qTrade': client = QtradeAPI('https://api.qtrade.io', key=credentials['api_key']) try: client.get("/v1/user/me") except: print('Invalid Credentials' + '\n') continue else: print('qTrade Credentials Verified' + '\n') break save_file(exchange + '_credentials', credentials) else: print('Change Existing ' + exchange + ' Credentials?') resp = y_n_prompt() if resp == 'No': while True: credentials = load_file(exchange + '_credentials') if exchange == 'Bitmex': client = bitmex(test=False, api_key=credentials['api_key'], api_secret=credentials['api_secret']) try: print('\n' + 'Testing Bitmex Credentials' + '\n') client.User.User_getWalletHistory().result() except bravado.exception.HTTPError: print('Invalid Credentials' + '\n') credentials = { 'exchange': exchange, 'api_key': str( input('Input Your ' + exchange + ' API Key' + '\n' + '> ')), 'api_secret': str( input('Input Your ' + exchange + ' API Secret' + '\n' + '> ')), } save_file(exchange + '_credentials', credentials) continue else: print('Bitmex Credentials Verified' + '\n') break elif exchange == 'Bybit': client = bybit(test=False, api_key=credentials['api_key'], api_secret=credentials['api_secret']) resp = client.APIkey.APIkey_info().result()[0]['ret_msg'] if resp == 'invalid api_key': print('Invalid Credentials' + '\n') credentials = { 'exchange': exchange, 'api_key': str( input('Input Your ' + exchange + ' API Key' + '\n' + '> ')), 'api_secret': str( input('Input Your ' + exchange + ' API Secret' + '\n' + '> ')), } save_file(exchange + '_credentials', credentials) continue else: print('Bybit Credentials Verified' + '\n') break elif exchange == 'qTrade': client = QtradeAPI('https://api.qtrade.io', key=credentials['api_key']) try: client.get("/v1/user/me") except: print('Invalid Credentials' + '\n') credentials = { 'exchange': exchange, 'api_key': str( input('Input Your ' + exchange + ' API Key' + '\n' + '> ')) } save_file(exchange + '_credentials', credentials) continue else: print('qTrade Credentials Verified' + '\n') break while bot: credentials = load_file(exchange + '_credentials') try: credentials['bot_token'] == True except KeyError: credentials.update({ 'bot_token': str(input('Input Your Telegram Bot API Key' + '\n' + '> ')), 'bot_chatID': str(input('Input Your Telegram User ChatID' + '\n' + '> ')), }) test_msg = telegram_sendText( (credentials['bot_token'], credentials['bot_chatID']), 'Testing')['ok'] if test_msg: print('\n' + 'Confirm Test Message Receipt') resp = y_n_prompt() if resp == 'No': print('Try Again' + '\n') continue else: print('Bot Credentials Verified' + '\n') save_file(exchange + '_credentials', credentials) bot = (credentials['bot_token'], credentials['bot_chatID']) else: print('Test Message Failed. Reenter Bot Credentials' + '\n') continue else: print('Change Existing Bot Credentials?') resp = y_n_prompt() if resp == 'Yes': credentials['bot_token'] = str( input('Input Your Telegram Bot API Key' + '\n' + '> ')) credentials['bot_chatID'] = str( input('Input Your Telegram User ChatID' + '\n' + '> ')) test_msg = telegram_sendText( (credentials['bot_token'], credentials['bot_chatID']), 'Testing')['ok'] if test_msg: print('\n' + 'Confirm Test Message Receipt') resp = y_n_prompt() if resp == 'No': print('Try Again' + '\n') continue else: print('Bot Credentials Verified' + '\n') save_file(exchange + '_credentials', credentials) bot = (credentials['bot_token'], credentials['bot_chatID']) else: print('Test Message Failed. Reenter Bot Credentials' + '\n') continue else: bot = (credentials['bot_token'], credentials['bot_chatID']) break return client, bot
def load_credentials(exchange, bot): credentials = load_file(exchange + '_credentials') client = QtradeAPI('https://api.qtrade.io', key=credentials['api_key']) if bot == True: bot = (credentials['bot_token'], credentials['bot_chatID']) return client, bot
from qtrade_client.api import QtradeAPI def load_credentials(): with open("secret") as authfile: return authfile.read() # String is of the format "[key_id]:[key]" client_native = QtradeAPI("https://api.qtrade.io", key=load_credentials()) # result = client.post("/v1/user/sell_limit", amount="1", price="0.0001", market_id=12) # print(result) # Only closed orders print(client_native.orders(open=False)) # Print all orders before ID 25 print(client_native.orders(older_than=25)) # Print all orders after ID 25 print(client_native.orders(newer_than=25))
def api_with_market(): api = QtradeAPI("http://localhost:9898/") # manually set lazily loaded properties api._markets_map = { "LTC_BTC": { "base_currency": { "can_withdraw": True, "code": "BTC", "config": { "address_version": 0, "default_signer": 6, "explorerAddressURL": "https: //live.blockcypher.com/btc/address/", "explorerTransactionURL": "https: //live.blockcypher.com/btc/tx/", "p2sh_address_version": 5, "price": 8614.27, "required_confirmations": 2, "required_generate_confirmations": 100, "satoshi_per_byte": 15, "withdraw_fee": "0.0005", }, "long_name": "Bitcoin", "metadata": { "withdraw_notices": [] }, "precision": 8, "status": "ok", "type": "bitcoin_like", }, "can_cancel": True, "can_trade": True, "can_view": True, "id": 1, "maker_fee": "0", "market_currency": { "can_withdraw": True, "code": "LTC", "config": { "additional_versions": [5], "address_version": 48, "default_signer": 5, "explorerAddressURL": "https: //live.blockcypher.com/ltc/address/", "explorerTransactionURL": "https: //live.blockcypher.com/ltc/tx/", "p2sh_address_version": 50, "price": 58.73, "required_confirmations": 10, "required_generate_confirmations": 100, "satoshi_per_byte": 105, "withdraw_fee": "0.001", }, "long_name": "Litecoin", "metadata": {}, "precision": 8, "status": "ok", "type": "bitcoin_like", }, "metadata": {}, "string": "LTC_BTC", "taker_fee": "0.005", }, 1: { "base_currency": { "can_withdraw": True, "code": "BTC", "config": { "address_version": 0, "default_signer": 6, "explorerAddressURL": "https: //live.blockcypher.com/btc/address/", "explorerTransactionURL": "https: //live.blockcypher.com/btc/tx/", "p2sh_address_version": 5, "price": 8614.27, "required_confirmations": 2, "required_generate_confirmations": 100, "satoshi_per_byte": 15, "withdraw_fee": "0.0005", }, "long_name": "Bitcoin", "metadata": { "withdraw_notices": [] }, "precision": 8, "status": "ok", "type": "bitcoin_like", }, "can_cancel": True, "can_trade": True, "can_view": True, "id": 1, "maker_fee": "0", "market_currency": { "can_withdraw": True, "code": "LTC", "config": { "additional_versions": [5], "address_version": 48, "default_signer": 5, "explorerAddressURL": "https: //live.blockcypher.com/ltc/address/", "explorerTransactionURL": "https: //live.blockcypher.com/ltc/tx/", "p2sh_address_version": 50, "price": 58.73, "required_confirmations": 10, "required_generate_confirmations": 100, "satoshi_per_byte": 105, "withdraw_fee": "0.001", }, "long_name": "Litecoin", "metadata": {}, "precision": 8, "status": "ok", "type": "bitcoin_like", }, "metadata": {}, "string": "LTC_BTC", "taker_fee": "0.005", }, } api._tickers = { 1: { "ask": "0.00707017", "bid": "0.00664751", "day_avg_price": "0.0071579647440367", "day_change": "0.0173330516998029", "day_high": "0.00727268", "day_low": "0.00713415", "day_open": "0.00714877", "day_volume_base": "0.00169664", "day_volume_market": "0.23702827", "id": 1, "id_hr": "LTC_BTC", "last": "0.00727268", }, "LTC_BTC": { "ask": "0.00707017", "bid": "0.00664751", "day_avg_price": "0.0071579647440367", "day_change": "0.0173330516998029", "day_high": "0.00727268", "day_low": "0.00713415", "day_open": "0.00714877", "day_volume_base": "0.00169664", "day_volume_market": "0.23702827", "id": 1, "id_hr": "LTC_BTC", "last": "0.00727268", }, } # prevent lazily loaded properties from updating and making http calls def ret(*args, **kwargs): return api._refresh_tickers = ret api._refresh_common = ret return api
def api(): return QtradeAPI("http://localhost:9898/")
def __init__(self, **kwargs): self.api = QtradeAPI("https://api.qtrade.io", key=open("lpbot_hmac.txt", "r").read().strip()) super().__init__(**kwargs)
class OrderbookManager: def __init__(self, endpoint, key, config): self.config = config self.api = QtradeAPI(endpoint, key=key) self.prev_alloc_profile = None self.market_configs = { ms: MarketConfig(ms, mkt, default=config['markets'].get('default')) for ms, mkt in config['markets'].items() if ms != 'default' } def compute_allocations(self): """ Given our allocation % targets and our current balances, figure out how much market and base currency we would _ideally_ be allocating to each market return { "DOGE_BTC": [1200, 0.0012], } """ balances = { c: Decimal(b) for c, b in self.api.balances_merged().items() } balances.update({ c: 0 for c in self.config['currency_reserves'] if c not in balances.keys() }) reserve_config = self.config['currency_reserves'] allocs = {} for market_string, market_alloc in self.market_configs.items(): market = self.api.markets[market_string] def allocate_coin(coin): """ Factor in allocation precentage and reserve amount to determine how much (base|market)-currency we're going to allocate to orders on this particular market. """ reserve = Decimal(reserve_config[coin]) alloc_perc = Decimal(market_alloc[coin]) post_reserve = balances[coin] - reserve return max(post_reserve * alloc_perc, 0) market_amount = allocate_coin(market['market_currency']['code']) base_amount = allocate_coin(market['base_currency']['code']) # TODO: At some point COIN will need to be based off base currency # precision. Not needed until we have ETH base markets really allocs[market_string] = (market_amount, base_amount) return allocs def allocate_orders(self, market_alloc, base_alloc, market_string): """ Given some amount of base and market currency determine how we'll allocate orders. Returns a tuple of (slippage_ratio, currency_allocation) return { "buy_limit": [ (0.01, 0.00001256), ], "sell_limit": [ (0.01, 1250), ] } """ buy_allocs = [] sell_allocs = [] mc = self.market_configs[market_string] for slip, ratio in mc['intervals']['sell_limit'].items(): ratio = Decimal(ratio) amount = (market_alloc * ratio).quantize(COIN) sell_allocs.append((slip, amount)) for slip, ratio in mc['intervals']['buy_limit'].items(): ratio = Decimal(ratio) value = (base_alloc * ratio).quantize(COIN) buy_allocs.append((slip, value)) return {'buy_limit': buy_allocs, 'sell_limit': sell_allocs} def price_orders(self, orders, bid, ask): """ return { "buy_limit": [ (0.00000033, 0.00001256), ], "sell_limit": [ (0.00000034, 1250), ] } """ priced_sell_orders = [] priced_buy_orders = [] bid = Decimal(bid) ask = Decimal(ask) for slip, amount in orders['sell_limit']: slip = Decimal(slip) price = (ask + (ask * slip)).quantize(COIN) priced_sell_orders.append((price, amount)) for slip, value in orders['buy_limit']: slip = Decimal(slip) price = (bid - (bid * slip)).quantize(COIN) priced_buy_orders.append((price, value)) return { 'buy_limit': priced_buy_orders, 'sell_limit': priced_sell_orders } def rebalance_orders(self, allocation_profile, orders, force=False): if self.check_for_rebalance( allocation_profile) is False and force is False: return if self.config['dry_run_mode']: log.warning( "You are in dry run mode! Orders will not be cancelled or placed!" ) pprint(allocation_profile) return self.api.cancel_all_orders() for market_string, profile in allocation_profile.items(): for price, value in profile['buy_limit']: self.place_order('buy_limit', market_string, price, value) for price, amount in profile['sell_limit']: self.place_order('sell_limit', market_string, price, amount) self.prev_alloc_profile = allocation_profile def place_order(self, order_type, market_string, price, quantity): if quantity <= 0: return log.info("Placing %s on %s market for %s at %s", order_type, market_string, quantity, price) if order_type == 'buy_limit': value = quantity amount = None elif order_type == 'sell_limit': value = None amount = quantity try: self.api.order(order_type, price, market_string=market_string, value=value, amount=amount, prevent_taker=False) except APIException as e: if e.code == 400: log.warning("Caught API error!") else: raise e def check_for_rebalance(self, allocation_profile): if self.prev_alloc_profile is None: log.info("Rebalance! No previous rebalance data!") return True for market, profile in allocation_profile.items(): prev_profile = self.prev_alloc_profile[market] for t in ('buy_limit', 'sell_limit'): for n, o in zip(profile[t], prev_profile[t]): price_diff = (n[0] - o[0]) / n[0] price_tol = self.config['price_tolerance'] if price_diff > price_tol: if o[0] > price_diff: log.info( 'Rebalance! %s %s price is %s%% higher than allotted', market, t, price_diff.quantize(PERC) * Decimal(100)) else: log.info( 'Rebalance! %s %s price is %s%% lower than allotted', market, t, price_diff.quantize(PERC) * Decimal(100)) return True if n[1] == 0: continue amount_diff = (n[1] - o[1]) / n[1] amount_tol = self.config['amount_tolerance'] if amount_diff > amount_tol: if o[1] > amount_diff: log.info( 'Rebalance! %s %s amount is %s%% higher than allotted', market, t, amount_diff.quantize(PERC) * Decimal(100)) else: log.info( 'Rebalance! %s %s amount is %s%% lower than allotted', market, t, amount_diff.quantize(PERC) * Decimal(100)) return True balances = self.api.balances() for coin, reserve in self.config['currency_reserves'].items(): balance_usd = self.coin_to_usd(coin, balances.get(coin, 0)) reserve_usd = self.coin_to_usd(coin, reserve) thresh = Decimal(self.config['reserve_thresh_usd']) if balance_usd > reserve_usd + thresh: log.info( f"Rebalance! {coin} balance_usd {balance_usd} > reserve {reserve} + thresh {thresh}." ) return True if balance_usd < reserve_usd - thresh: log.info( f"Rebalance! {coin} balance_usd {balance_usd} < reserve {reserve} - thresh {thresh}." ) return True return False def get_orders(self): orders = self.api.get("/v1/user/orders")["orders"] log.debug("Updating orders...") sorted_orders = {} for o in orders: if o['open']: mi = self.api.get("/v1/market/" + str(o['market_id']))['market'] o['price'] = Decimal(o['price']) o['market_amount_remaining'] = Decimal( o['market_amount_remaining']) o['base_amount'] = o['price'] * o['market_amount_remaining'] market = mi['market_currency'] + '_' + mi['base_currency'] sorted_orders.setdefault(market, {'buy': [], 'sell': []}) if o["order_type"] == "sell_limit": sorted_orders[market]['sell'].append(o) elif o["order_type"] == "buy_limit": sorted_orders[market]['buy'].append(o) log.debug("Active buy orders: %s", sorted_orders) log.info( "%s active buy orders", sum([len(market['buy']) for market in sorted_orders.values()])) log.info( "%s active sell orders", sum([len(market['sell']) for market in sorted_orders.values()])) return sorted_orders def generate_orders(self, force_rebalance=False): allocs = self.compute_allocations() allocation_profile = {} for market, (market_amount, base_amount) in allocs.items(): if market in ExchangeDatastore.tickers['bittrex'].keys(): bid = ExchangeDatastore.tickers['bittrex'][market]['bid'] ask = ExchangeDatastore.tickers['bittrex'][market]['ask'] elif market in ExchangeDatastore.tickers['ccxt'].keys(): bid = ExchangeDatastore.tickers['ccxt'][market]['bid'] ask = ExchangeDatastore.tickers['ccxt'][market]['ask'] else: log.warning( f"Can't get bid/ask price for {market} to generate orders!" ) continue log.info("Generating %s orders with bid %s and ask %s", market, bid, ask) allocation_profile[market] = self.price_orders( self.allocate_orders(market_amount, base_amount, market), bid, ask) self.rebalance_orders(allocation_profile, self.get_orders(), force=force_rebalance) def estimate_account_value(self): # convert all coin values to BTC using the Bittrex bid price # then convert to USD total_bal = 0 bals = self.api.balances_merged() for coin, bal in bals.items(): if coin == "BTC": total_bal += Decimal(bal) else: total_bal += self.coin_to_btc(coin, bal) return total_bal, self.btc_to_usd(total_bal).quantize(PERC) def estimate_account_gain(self, btc_bal): cost_basis = Decimal(self.config['cost_basis_btc']) gain = (btc_bal - cost_basis).quantize(COIN) return gain, self.btc_to_usd(gain).quantize(PERC) def coin_to_btc(self, coin, amt): exchanges = ['bittrex', 'ccxt', 'qtrade'] for e in exchanges: try: bid = ExchangeDatastore.tickers[e][coin + '_BTC']['bid'] return (Decimal(amt) * Decimal(bid)).quantize(COIN) except KeyError: pass log.warning("Can't get bid price for %s for price estimation", coin) return 0 def btc_to_usd(self, amt): btc_price = Decimal( self.api.get('/v1/currency/BTC')['currency']['config']['price']) return Decimal(amt) * btc_price def coin_to_usd(self, coin: str, amt: Union[Decimal, float]) -> Decimal: if coin == "BTC": return self.btc_to_usd(amt) return self.btc_to_usd(self.coin_to_btc(coin, amt)).quantize(PERC) def boot_trades(self): trades = { t['id']: t for t in self.api.get('/v1/user/trades')['trades'] } newest_ids = heapq.nlargest(10, trades.keys()) recent_trades = {id: trades[id] for id in newest_ids} self.most_recent_trade_id = max(newest_ids) log.info("10 most recent trades:\n%s", pformat(recent_trades)) def check_for_trades(self): res = self.api.get('/v1/user/trades', newer_than=self.most_recent_trade_id) if res['trades'] == []: log.info('No new trades!') return trades = {t['id']: t for t in res['trades']} log.info("Bot made new trades:\n%s", pformat(trades)) self.most_recent_trade_id = max(trades.keys()) async def monitor(self): # Sleep to allow data scrapers to populate await asyncio.sleep(2) log.info("Starting orderbook manager; interval period %s sec", self.config['monitor_period']) self.boot_trades() while True: try: self.generate_orders() btc_val, usd_val = self.estimate_account_value() log.info("Current account value is about $%s, %s BTC", usd_val, btc_val) btc_gain, usd_gain = self.estimate_account_gain(btc_val) log.info("The bot has earned $%s, %s BTC", usd_gain, btc_gain) self.check_for_trades() await asyncio.sleep(self.config['monitor_period']) except Exception: log.warning("Orderbook manager loop exploded", exc_info=True) # Just in case the entire program explodes, so that we don't have orders out. self.api.cancel_market_orders()