class TestBittrexAccountAPI(unittest.TestCase): def setUp(self): self.bittrex = Bittrex() def test_get_balances(self): actual = self.bittrex.get_balances() test_basic_response(self, actual, 'get_balances') def test_get_balance(self): self.assertRaises(TypeError, self.bittrex.get_balance) actual = self.bittrex.get_balance('BTC') test_basic_response(self, actual, 'get_balance') invalid_actual = self.bittrex.get_balance('Invalid currency') test_failed_response(self, invalid_actual, 'get_balance') def test_get_deposit_address(self): self.assertRaises(TypeError, self.bittrex.get_deposit_address) actual = self.bittrex.get_deposit_address('BTC') test_basic_response(self, actual, 'get_deposit_address') invalid_actual = self.bittrex.get_deposit_address('Invalid currency') test_failed_response(self, invalid_actual, 'get_deposit_address') def test_withdraw(self): self.assertRaises(TypeError, self.bittrex.withdraw) def test_get_order(self): self.assertRaises(TypeError, self.bittrex.get_order) actual = self.bittrex.get_order('test') test_response_structure(self, actual, 'get_order') def test_get_order_history(self): actual = self.bittrex.get_order_history() test_basic_response(self, actual, 'get_order_history') actual = self.bittrex.get_order_history('BTC-LTC') test_basic_response(self, actual, 'get_order_history') def test_get_withdrawal_historyself(self): actual = self.bittrex.get_withdrawal_history() test_basic_response(self, actual, 'get_withdrawal_history') actual = self.bittrex.get_withdrawal_history('BTC') test_basic_response(self, actual, 'get_withdrawal_history') def test_get_deposit_history(self): actual = self.bittrex.get_deposit_history() test_basic_response(self, actual, 'get_deposit_history') actual = self.bittrex.get_deposit_history('BTC') test_basic_response(self, actual, 'get_deposit_history')
class BittrexClient: def __init__(self, config: BittrexConfig) -> None: self.config = config.value self.bitrex_client = Bittrex(api_key="XXXXXXXXXXXXXX", api_secret="XXXXXXXXXXXXX") def get_available_coin_volume(self) -> None: coins = self.config['available_coins'] for coin in coins: btc_volume_dict = self.bitrex_client.get_balance(coin) # data = json.load(btc_volume_json) btc_volume_dict = self._parse_result(btc_volume_dict) # for header, value in btc_volume_dict.items(): # print("{x} {y}".format(x=header, y=value)) # if btc_volume_dict.get('Available'): # print('Available {0:} in your account is {1:0.10f}'.format(coin, btc_volume_dict.get('Available'))) # else: # print('Available {0:} in your account is {1:}'.format(coin, btc_volume_dict.get('Available'))) def get_current_market(self) -> dict: markets = self.config['monitor_markets'] result = dict() for market in markets: market_name = None while market != market_name: market_name, ask_value = self.get_market(market) result.update({market_name: ask_value}) return result def get_market(self, market: str) -> tuple: result = dict() market_value = self.bitrex_client.get_marketsummary(market=market) market_value = self._parse_result(market_value) ask_value = market_value[0].get('Last') market_name = market_value[0].get('MarketName') print("Last Traded value of {0:} : {1:0.10f} BTC".format( market_name, ask_value)) result[market_name] = ask_value return market_name, ask_value @staticmethod def _parse_result(raw_response: dict) -> dict: # Todo: check response status to be success response = raw_response['result'] return response
def handle_bittrex_balance(message): my_b = Bittrex(auth.api_key, auth.api_secret) balance = my_b.get_balance('ZEC') zec_value = balance['result']['Available'] bot.send_message(message.chat.id, zec_value)
class TestBittrexV20AccountAPI(unittest.TestCase): """ Integration tests for the Bittrex Account API. * These will fail in the absence of an internet connection or if bittrex API goes down. * They require a valid API key and secret issued by Bittrex. * They also require the presence of a JSON file called secrets.json. It is structured as such: { "key": "12341253456345", "secret": "3345745634234534" } """ def setUp(self): with open("secrets.json") as secrets_file: self.secrets = json.load(secrets_file) secrets_file.close() self.bittrex = Bittrex(self.secrets['key'], self.secrets['secret'], api_version=API_V2_0) def test_handles_invalid_key_or_secret(self): self.bittrex = Bittrex('invalidkey', self.secrets['secret'], api_version=API_V2_0) actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'Invalid key, valid secret') self.bittrex = Bittrex(None, self.secrets['secret'], api_version=API_V2_0) actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'None key, valid secret') self.bittrex = Bittrex(self.secrets['key'], 'invalidsecret', api_version=API_V2_0) actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'valid key, invalid secret') self.bittrex = Bittrex(self.secrets['key'], None, api_version=API_V2_0) actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'valid key, None secret') self.bittrex = Bittrex('invalidkey', 'invalidsecret', api_version=API_V2_0) actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'invalid key, invalid secret') def test_get_openorders(self): actual = self.bittrex.get_open_orders('BTC-LTC') test_basic_response(self, actual, "get_openorders") self.assertTrue(isinstance(actual['result'], list), "result is not a list") def test_get_balances(self): actual = self.bittrex.get_balances() test_basic_response(self, actual, "get_balances") self.assertTrue(isinstance(actual['result'], list), "result is not a list") @unittest.skip( "the return result is an empty dict. API bug? the 2.0 get_balances works as expected" ) def test_get_balance(self): actual = self.bittrex.get_balance('BTC') test_basic_response(self, actual, "get_balance") self.assertTrue(isinstance(actual['result'], dict), "result is not a dict") self.assertEqual( actual['result']['Currency'], "BTC", "requested currency {0:s} does not match returned currency {1:s}". format("BTC", actual['result']['Currency'])) @unittest.skip("my testing account is acting funny this should work") def test_get_depositaddress(self): actual = self.bittrex.get_deposit_address('BTC') test_basic_response(self, actual, "get_deposit_address") def test_get_order_history_all_markets(self): actual = self.bittrex.get_order_history() test_basic_response(self, actual, "get_order_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_order_history_one_market(self): actual = self.bittrex.get_order_history(market='BTC-LTC') test_basic_response(self, actual, "get_order_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_withdrawlhistory_all_currencies(self): actual = self.bittrex.get_withdrawal_history() test_basic_response(self, actual, "get_withdrawal_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_withdrawlhistory_one_currency(self): actual = self.bittrex.get_withdrawal_history('BTC') test_basic_response(self, actual, "get_withdrawal_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_deposithistory_all_currencies(self): actual = self.bittrex.get_deposit_history() test_basic_response(self, actual, "get_deposit_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_deposithistory_one_currency(self): actual = self.bittrex.get_deposit_history('BTC') test_basic_response(self, actual, "get_deposit_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_pending_withdrawals_all_currencies(self): actual = self.bittrex.get_pending_withdrawals() test_basic_response(self, actual, "get_pending_withdrawals") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_pending_withdrawals_one_currency(self): actual = self.bittrex.get_pending_withdrawals('BTC') test_basic_response(self, actual, "get_pending_withdrawals") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_pending_deposits_all_currencies(self): actual = self.bittrex.get_pending_deposits() test_basic_response(self, actual, "get_pending_deposits") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_pending_deposits_one_currency(self): actual = self.bittrex.get_pending_deposits('BTC') test_basic_response(self, actual, "get_pending_deposits") self.assertIsInstance(actual['result'], list, "result is not a list") def test_generate_deposit_address(self): actual = self.bittrex.generate_deposit_address(currency='BTC') test_basic_response(self, actual, "generate_deposit_address") self.assertIsInstance(actual['result'], list, "result is not a list")
class TestBittrexV11AccountAPI(unittest.TestCase): """ Integration tests for the Bittrex Account API. * These will fail in the absence of an internet connection or if bittrex API goes down. * They require a valid API key and secret issued by Bittrex. * They also require the presence of a JSON file called secrets.json. It is structured as such: { "key": "12341253456345", "secret": "3345745634234534" } """ def setUp(self): with open("secrets.json") as secrets_file: self.secrets = json.load(secrets_file) secrets_file.close() self.bittrex = Bittrex(self.secrets['key'], self.secrets['secret']) def test_handles_invalid_key_or_secret(self): self.bittrex = Bittrex('invalidkey', self.secrets['secret']) actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'Invalid key, valid secret') self.bittrex = Bittrex(None, self.secrets['secret']) actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'None key, valid secret') self.bittrex = Bittrex(self.secrets['key'], 'invalidsecret') actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'valid key, invalid secret') self.bittrex = Bittrex(self.secrets['key'], None) actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'valid key, None secret') self.bittrex = Bittrex('invalidkey', 'invalidsecret') actual = self.bittrex.get_balance('BTC') test_auth_basic_failures(self, actual, 'invalid key, invalid secret') def test_get_openorders(self): actual = self.bittrex.get_open_orders('BTC-LTC') test_basic_response(self, actual, "get_openorders") self.assertTrue(isinstance(actual['result'], list), "result is not a list") def test_get_balances(self): actual = self.bittrex.get_balances() test_basic_response(self, actual, "get_balances") self.assertTrue(isinstance(actual['result'], list), "result is not a list") def test_get_balance(self): actual = self.bittrex.get_balance('BTC') test_basic_response(self, actual, "get_balance") self.assertTrue(isinstance(actual['result'], dict), "result is not a dict") self.assertEqual( actual['result']['Currency'], "BTC", "requested currency {0:s} does not match returned currency {1:s}". format("BTC", actual['result']['Currency'])) def test_get_depositaddress(self): actual = self.bittrex.get_deposit_address('BTC') if not actual['success']: self.assertTrue(actual['message'], 'ADDRESS_GENERATING') else: test_basic_response(self, actual, "get_deposit_address") def test_get_order_history_all_markets(self): actual = self.bittrex.get_order_history() test_basic_response(self, actual, "get_order_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_order_history_one_market(self): actual = self.bittrex.get_order_history(market='BTC-LTC') test_basic_response(self, actual, "get_order_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_withdrawlhistory_all_currencies(self): actual = self.bittrex.get_withdrawal_history() test_basic_response(self, actual, "get_withdrawal_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_withdrawlhistory_one_currency(self): actual = self.bittrex.get_withdrawal_history('BTC') test_basic_response(self, actual, "get_withdrawal_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_deposithistory_all_currencies(self): actual = self.bittrex.get_deposit_history() test_basic_response(self, actual, "get_deposit_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_deposithistory_one_currency(self): actual = self.bittrex.get_deposit_history('BTC') test_basic_response(self, actual, "get_deposit_history") self.assertIsInstance(actual['result'], list, "result is not a list") def test_get_pending_withdrawals(self): self.assertRaisesRegexp(Exception, 'method call not available', self.bittrex.get_pending_withdrawals) def test_get_pending_deposits(self): self.assertRaisesRegexp(Exception, 'method call not available', self.bittrex.get_pending_deposits) def test_generate_deposit_address(self): self.assertRaisesRegexp(Exception, 'method call not available', self.bittrex.generate_deposit_address, currency='BTC')
from bittrex import Bittrex my_bittrex = Bittrex("<my_api_key>", "<my_api_secret>", api_version="<API_V1_1> or <API_V2_0>") my_bittrex.get_balance('ETH') { 'success': True, 'message': '', 'result': { 'Currency': 'ETH', 'Balance': 0.0, 'Available': 0.0, 'Pending': 0.0, 'CryptoAddress': None } }
class TradeBot(): def __init__(self, key=None, secret=None, **kwargs): self.exchange = Bittrex(key, secret) self.orders = [] # Default config config = { 'base_currency': 'ETH', 'min_order': 0.001, 'max_order': 0.05, 'sleep_time': 60, 'profit': 2, 'min_volume': 75, 'max_units': 100 } # Update config from object constructor config.update(kwargs) # Set attributes based on config for attr in config.keys(): setattr(self, attr, config[attr]) def get_markets(self): logging.info(f'Getting markets for {self.base_currency}') all_markets = self.exchange.get_markets()['result'] markets = set() for mkt in all_markets: if mkt['BaseCurrency'] == self.base_currency: markets.add(mkt['MarketName']) return markets def get_coins_with_open_orders(self): open_orders = self.exchange.get_open_orders()['result'] if len(open_orders) == 0: return [] else: return [x['Exchange'] for x in open_orders] def get_market_data(self): mkt_data = [] for mkt in self.markets: logging.info(f'Getting market data for {mkt}') data = self.exchange.get_marketsummary(mkt)['result'][0] data['Change'] = calculate_change(data['Last'], data['Low']) mkt_data.append(data) return mkt_data def has_balance_to_buy(self): logging.info('checking if we have some balance to buy') q = self.exchange.get_balance(self.base_currency) # balance_adjustment to avoid INSUFFICIENT FUNDS MESSAGE balance_adjustment = 0.0005 self.balance = q['result']['Available'] - balance_adjustment logging.debug(f'{self.balance}{self.base_currency} available') if self.balance >= self.min_order: return True else: return False def get_market_to_buy(self): self.update() mkt = [ m for m in self.market_data if m['BaseVolume'] >= self.min_volume ] sorted_mkt = sorted(mkt, key=lambda x: x['BaseVolume'], reverse=True) while sorted_mkt[0]['MarketName'] in self.coins_with_open_orders: sorted_mkt.pop(0) return sorted_mkt[0] def buy(self, mkt): coin = mkt['MarketName'] # get a price between ask and bid price = (mkt['Ask'] + mkt['Bid']) / 2 if self.balance > self.max_order: qnt = self.max_order / price else: qnt = self.balance / price if qnt > self.max_units: qnt = self.max_units if (qnt * price) < self.min_order: qnt = self.min_order / price logging.info(f'BUY {qnt} {coin} - price {price}, total {price * qnt}') order = self.exchange.buy_limit(coin, qnt, price) if order['success']: self.orders.append(order['result']['uuid']) else: logging.error(f'BUY FAIL - {order}') return (order) def sell(self): for order in self.orders: order_info = self.exchange.get_order(order)['result'] if order_info['Closed']: coin = order_info['Exchange'] qnt = order_info['Quantity'] price = profit(order_info['PricePerUnit'], self.profit) sell_order = self.exchange.sell_limit(coin, qnt, price) self.orders.remove(order) logging.info(f'SELL {order} {sell_order}') def update(self): logging.info('Updating data') self.markets = self.get_markets() self.market_data = self.get_market_data() self.coins_with_open_orders = self.get_coins_with_open_orders() def do_trade(self): if self.has_balance_to_buy(): self.buy(self.get_market_to_buy()) if len(self.orders) > 0: self.sell() logging.info(f'Sleeping for {self.sleep_time} seconds') sleep(self.sleep_time) def run(self): logging.info('Starting Bot') while True: self.do_trade()
from __future__ import print_function import sys sys.path.append('/Users/jeffreytai/Documents/Science/bittrex') from bittrex import Bittrex import json from arbitrage_trading import Utils with open('secrets.json') as data_file: data = json.load(data_file) bt = Bittrex(data['deeson']['key'], data['deeson']['secret']) utils = Utils() balance = bt.get_balance('BTC') print("bitcoin balance") utils.pretty_print(balance) balance = bt.get_balance('ETH') print("ethereum balance") utils.pretty_print(balance)
class BittrexBuysellWorker(object): def __init__(self, key=None, secret=None, token=None): self.EXCHANGE_RATE = 0.9975 # 0.25% for each trading transaction self.api = Bittrex(key, secret) self.token = token try: m = self.api.get_market_summaries() #print m market_list = [] for market in m.get("result"): market_list.append(market.get("MarketName")) #print marketlist except: print "Error: Cannot get market summaries" exit(1) self.market_list = market_list def w_get_api(self): """ Get balance of a coin :return: api Bittrex.py :rtype : Bittrex class """ return self.api def w_get_balance(self, coin): """ Get balance of a coin :return: current balance value :rtype : float """ try: m = self.api.get_balance(coin) print m if (m.get("success")): v = m.get("result").get("Balance") return v if v else 0 else: print("Cannot get {} balance".format(coin)) return ERROR.CMD_UNSUCCESS except: print("Error Account/Connection issue. Get {} balance failed". format(coin)) return ERROR.CONNECTION_FAIL def w_get_market_name(self, coin1, coin2): """ Get marketname for pair of coins :param coin1: String literal for coin 1 (ex: USDT) :param coin2: String literal for coin 2 (ex: XMR) :return: (MarketName, "Buy"/"Sell") :rtype : str """ market = coin1 + "-" + coin2 if market in self.market_list: return (market, "Buy") else: market = coin2 + "-" + coin1 if market in self.market_list: return (market, "Sell") else: print "Error: Invalid coin pair" return (None, None) def w_get_price(self, market, type, unit=0, depth=20): """ Get price Ask Last Bid :param market: String literal for coin1-coin2 (ex: USDT-XMR) :param type: Ask/Last/Bid :param unit: if unit != 0, get price with respect to order book :return: price :rtype : float """ if type is "Last" or "Bid" or "Ask": try: price = self.api.get_marketsummary(market).get( "result")[0].get(type) if type == "Ask": ordertype = "sell" elif type == "Bid": ordertype = "buy" else: #Dont need to check order book for Last return price m = self.api.get_orderbook(market, ordertype, depth) #print m if (m.get("message") != ""): print "Fail to get order book of {}: {}".format( market, m.get("message")) return ERROR.CMD_UNSUCCESS else: order_price_list = m.get("result") #print order_price_list sum_quantity = 0 for o in order_price_list: #print o quantity = o.get("Quantity") price = o.get("Rate") sum_quantity += quantity if (sum_quantity >= unit): return price except: print("Error in get {} price".format(market)) return ERROR.CONNECTION_FAIL else: print("Invalid type of market (Ask/Bid/Last)") return ERROR.PARAMETERS_INVALID '''To do: unit != 0''' def w_get_open_order(self, market=None): """ Get list of uuid of open orders :param market: String literal for coin1-coin2 (ex: USDT-XMR) :return: uuid list :rtype : str """ return self.api.get_open_orders(market) def w_order_buy_sell(self, coin1, coin2, value1, price, timeout, cancel_on_timeout=True): """ Buy/Sell from coin c1 to coin coin2 at price :param coin1: String literal for coin 1 (ex: USDT) :param coin2: String literal for coin 2 (ex: XMR) :param value1: The value of coin1 which is used to buy/sell :param price: buy/sell price, can be Ask, Last or Bid :return: uuid order :rtype : str """ value2_before = self.w_get_balance(coin2) #get current coin2 balance market, type = self.w_get_market_name(coin1, coin2) #print market, type #Buy and sell are seperated from market point of view. if (type == "Buy"): order_buy_sell = self.api.buy_limit quantity = value1 / price * self.EXCHANGE_RATE value2 = quantity * self.EXCHANGE_RATE elif (type) == "Sell": order_buy_sell = self.api.sell_limit quantity = value1 value2 = quantity * price * self.EXCHANGE_RATE else: print "Buy/Sell Error: Invalid market {}-{}".format(coin1, coin2) return ERROR.CMD_INVALID print("@@@ From {} {} buy {} {} at price {}.".format( value1, coin1, value2, coin2, price)) #Process buy/sell within timeout #Several posible cases: # 1. The price is too high/low, no one wants to buy/sell # 2. The connection drops while waiting the result # 3. The quantity is too low -> "INSUFFICIENT_FUNDS" response from server try: m = order_buy_sell(market, quantity, price) if (m.get("success") == True): uuid = m.get("result").get("uuid") process_time = time.time() + timeout while 1: value2_after = self.w_get_balance(coin2) if time.time() > process_time: if cancel_on_timeout: #Cancel order because of timeout self.w_cancel_order(uuid) print "Cancel order!" else: print "Order is still open!" return uuid print "{} transaction was timeout".format(type) return ERROR.TIME_OUT if (value2_after < 0): #Error print "Error: in balance code {}".format(value2_after) return ERROR.CMD_UNSUCCESS if (value2_after - value2_before >= value2 * 0.9): #offset 10% for safety #buy success return uuid elif m.get("message") == "INSUFFICIENT_FUNDS": print("INSUFFICIENT_FUNDS issue") print m return ERROR.PARAMETERS_INVALID else: print m return ERROR.CMD_UNSUCCESS except: print "Error buy/sell. Conection failed." return ERROR.CONNECTION_FAIL def w_cancel_order(self, uuid): """ Cancel an order via uuid :param uuid: order uuid :return: error code :rtype : ERROR """ try: #todo: need check timeout self.api.cancel(uuid) while uuid in self.api.get_open_orders(): print "Wait for cancel order {}".format(uuid) return ERROR.CMD_SUCCESS except: print "Cannot cancel order {}".format(uuid) return ERROR.CONNECTION_FAIL def w_get_price_by_order_book(self, market, ordertype, value, depth=20): """ Get the corresponding price for a given value -> Avoid stuck in buy/sell order :param market: Ex: USDT-XMR :param ordertype: "buy" or "sell" :param value: The value of coin1 which is used to buy/sell :return: uuid order :rtype : str """ return 0
def getBuyAmount(self): my_bittrex = Bittrex('###', '###') btc_balance = my_bittrex.get_balance('BTC')['result']['Balance'] return (btc_balance/5)
def getTotalAmount(self): my_bittrex = Bittrex('####', '####') btc_balance = my_bittrex.get_balance('BTC')['result']['Balance'] return float(btc_balance)
from datetime import timedelta connect_str = "dbname='bittrex' user='******' host='localhost' password='******'" conn = psycopg2.connect(connect_str) cursor = conn.cursor() cursor.execute("select * from btxmarkethistory") rows = cursor.fetchall() colnames = [desc[0] for desc in cursor.description] # print(colnames) #set API key bittrex = Bittrex('e281fee0429e428b9a76f63cc842f12d', 'a131b56ec7f24696a74c6b6da853d1eb') #get balance - just to test integration actual = bittrex.get_balance('BTC') dataTuple = [] for value in coinsToWatch: ## get various market summaries specificMarketHistory = bittrex.get_market_history( (market + '-' + str(value)), 30) # print(str(marketSummary['result'])) if specificMarketHistory['success'] == True: for valuetwo in specificMarketHistory['result']: currentTime = datetime.now() previousMinuteTime_nonFormat = currentTime - timedelta( minutes=1) previousMinuteReplaceSeconds = previousMinuteTime_nonFormat.replace( second=0, microsecond=0)
mp_queue.put(msg) # mp_queue.task_done() # after running arbitrage, sleep for 5 seconds to avoid overloading API time.sleep(5) else: print(arbitrage_order.coin, "not profitable") with open('secrets.json') as data_file: data = json.load(data_file) bt = Bittrex(data['deeson']['key'], data['deeson']['secret']) utils = Utils(bt) print("Bitcoin") balance = bt.get_balance(BITCOIN) utils.pretty_print(balance) print("Ether") eth_balance = bt.get_balance(ETHEREUM) utils.pretty_print(eth_balance) # while balance['success']: # valid_coins = [] # # result = bt.get_currencies() # if (result['success']): # # gets list of coins that can be traded for both ETH and BTC # coins = [coin.get('Currency') for coin in result['result'] if coin.get('Currency') not in [ETHEREUM, BITCOIN, LITECOIN]] # for coin in coins: # try:
class CryptoCommander: def __init__(self, poloapicreds=['', ''], bittrexapicreds=['', '']): print( "Initializing Crypto Commander, Intelligent and Responsive Crypto-Currency Platform..." ) print( "Disclaimer!! You have launched this via command line, great caution is advised and the developers are NOT responsible for proper usage or lost coins!" ) print( "Notice - :: :: Bitcoin & Crypto-Currencies are largely untested and come with no assurances! Trade with care. :: ::" ) if poloapicreds == ['', '']: print( "No poloniex credentials found, skipping initialization. This may cause instability!" ) else: try: self.poloniexBot = poloniex(poloapicreds[0], poloapicreds[1]) self.btcBalance, self.btsBalance, self.clamBalance, self.dashBalance, self.dogeBalance, self.ethBalance, self.fctBalance, self.ltcBalance, self.maidBalance, self.strBalance, self.xmrBalance, self.xrpBalance, = Decimal( 0.0), Decimal(0.0), Decimal(0.0), Decimal(0.0), Decimal( 0.0), Decimal(0.0), Decimal(0.0), Decimal( 0.0), Decimal(0.0), Decimal(0.0), Decimal( 0.0), Decimal(0.0) except AttributeError: print( "An error occurred trying to initialize Poloniex functionality." ) if bittrexapicreds == ['', '']: print( "No bittrex credentials detected, skipping initialization. This may cause instability!" ) else: try: self.bittrexBot = Bittrex(bittrexapicreds[0], bittrexapicreds[1]) except AttributeError: print( "An error occurred trying to initialized Bittrex functionality." ) def convert_coinpair_poloniex(self, coinpair): return coinpair.replace('-', '_') def get_tickers_raw(self, market): # A clone of the bittrex get_markets() & poloniex returnTicker commands, in a unified stream. if market == 'poloniex': return self.poloniexBot.returnTicker() elif market == 'bittrex': return self.bittrexBot.get_markets() def get_coinpair_ticker_raw(self, market, coinpair): # Returns raw market information on coin pair on market if market == 'poloniex': coinpair = self.convert_coinpair_poloniex(coinpair) rawtickerdata = self.get_tickers_raw(market) for coinpairdata in rawtickerdata: if coinpairdata == coinpair: return rawtickerdata[coinpairdata] if market == 'bittrex': return self.bittrexBot.get_ticker(coinpair.capitalize()) def getTickerData(self, market, bitcoinMarketsOnly=True, activeOnly=True, printFriendly=False, decimalTypes=True): #if market == 'poloniex: if market == 'bittrex': cryptoCommandTickers = {'BTC': [], 'Other': []} btcMarketsList = cryptoCommandTickers['BTC'] otherMarketsList = cryptoCommandTickers['Other'] stagingList = [] if printFriendly == True: decimalTypes = False for ticker in self.bittrexBot.get_markets()['result']: if ticker != None: stagingList.append([ str(ticker['MarketName']), str(ticker['BaseCurrency']), bool(str(ticker['IsActive'])) ]) for ticker in self.bittrexBot.get_market_summaries()['result']: if ticker != None: for list in stagingList: if list[0] == str(ticker['MarketName']): list.extend([ ticker['High'], ticker['Low'], ticker['Ask'], ticker['Bid'], ticker['Last'], ticker['PrevDay'], ticker['Volume'], ticker['BaseVolume'], (ticker['High'] + ticker['Low'] / 2.0) ]) for list in stagingList: if list[1] == 'BTC': btcMarketsList.append(list) else: otherMarketsList.append(list) if printFriendly == True: for dictobject in cryptoCommandTickers: for list in cryptoCommandTickers[dictobject]: for n, listobject in enumerate(list): if type(listobject) == float: list[n] = format(listobject, '.8f') elif decimalTypes == True: for dictobject in cryptoCommandTickers: for list in cryptoCommandTickers[dictobject]: for n, listobject in enumerate(list): if type(listobject) == float: list[n] = Decimal(format(listobject, '.8f')) return cryptoCommandTickers def getActiveMarketCurrencies(self, market, appendString=''): currentMarketList = [] if market == 'poloniex': rawCoinPairData = self.poloniexBot.api_query('returnTicker') for coinPairData in rawCoinPairData: if str(rawCoinPairData[coinPairData]['isFrozen']) == '0': currentMarketList.append( str(coinPairData).split('_', 1)[1]) if market == 'bittrex': for coinData in self.bittrexBot.get_currencies()['result']: if coinData['IsActive'] == True: currentMarketList.append(appendString + str(coinData['Currency'])) return set(currentMarketList) def getCurrentBalance(self, market, coin): if market == 'poloniex': return self.poloniexBot.returnBalances()[coin.upper()] elif market == 'bittrex': return self.bittrexBot.get_balance(coin)['result']['Balance'] def getTopOrder(self, market, coinPair, buyOrders): if buyOrders == True: if market == 'poloniex': for i in self.poloniexBot.returnOrderBook( coinPair.replace('-', '_'))['bids']: return i elif market == 'bittrex': for i in self.bittrexBot.get_orderbook(coinPair, 'buy')['result']: return i else: print('Not a valid market: ' + str(market)) else: if market == 'poloniex': for i in self.poloniexBot.returnOrderBook( coinPair.replace('-', '_'))['asks']: return i elif market == 'bittrex': for i in self.bittrexBot.get_orderbook(coinPair, 'sell')['results']: return i else: print('Not a valid market: ' + str(market)) def getWalletAddress(self, market, coin): if market == "poloniex" or market == "Poloniex": return self.poloniexBot.api_query('returnDepositAddresses')[coin] elif market == "bittrex" or market == "Bittrex": return self.bittrexBot.get_balance(coin)['result']['CryptoAddress'] def compareMarkets(self, market1, market2): currentActiveMarketsLists = [ self.getActiveMarketCurrencies(market1), self.getActiveMarketCurrencies(market2) ] comparisonList = [] for i in currentActiveMarketsLists[0]: for y in currentActiveMarketsLists[1]: if i == y: comparisonList.append(i) else: continue return comparisonList def getCoinPairPriceDifferencePercent(self, buyPrice, sellPrice): return (((float(buyPrice) - float(sellPrice)) / float(buyPrice)) * 100.00) def arbitrageScan(self, market1, market2, minPercent=0.45): try: arbOpportunitiesList = [] for coinpair in self.doMarketComparison(market1, market2): print("Scanning Coin Pair : " + str(coinpair)) differenceBetweenMarket1and2 = format( self.getCoinPairPriceDifferencePercent( float(self.getTopOrder(market1, coinpair, False, 1)), float(self.getTopOrder(market2, coinpair, True, 1)))) differenceBetweenMarket2and1 = format( self.getCoinPairPriceDifferencePercent( float(self.getTopOrder(market2, coinpair, False, 1)), float(self.getTopOrder(market1, coinpair, True, 1)))) if float(differenceBetweenMarket2and1) < (-.525 - minPercent): if (float(self.getTopOrder(market1, coinpair, True)[0]) * float( self.getTopOrder(market1, coinpair, True)[1]) ) >= float(self.getCurrentBalance(market1, "BTC")): print("Arb Op: " + str(differenceBetweenMarket2and1) + " for coin pair ") print("Info: Bittrex: Buy:: ") print(self.getTopOrder('bittrex', coinpair, True)) print("- Sell:: ") print(self.getTopOrder('bittrex', coinpair, False)) arbOpportunity = (coinpair, "Market2to1", differenceBetweenMarket2and1, 1) arbOpportunitiesList.append(arbOpportunity) else: continue elif float(differenceBetweenMarket1and2) < (-.525 - minPercent): if float( self.getTopOrder('bittrex', coinpair, True, 3)[0] ) * float(self.getTopOrder( 'bittrex', coinpair, True)[1]) >= float( self.getCurrentBalance(market2, "BTC")): print("Arb Op: ") print(str(differenceBetweenMarket1and2)) print("Info: Bittrex: Buy:: ") print(self.getTopOrder('poloniex', coinpair, True)) print("- Sell:: ") print(self.getTopOrder('poloniex', coinpair, False)) print("Info: Poloniex: Buy:: ") print(self.getTopOrder('bittrex', coinpair, True)) print("- Sell:: ") print(self.getTopOrder('bittrex', coinpair, False)) arbOpportunity = (coinpair, "Market1to2", differenceBetweenMarket1and2, 1) arbOpportunitiesList.append(arbOpportunity) else: continue else: print(differenceBetweenMarket1and2 + " or " + differenceBetweenMarket2and1 + " is more than -.7") continue return arbOpportunitiesList except AttributeError: print("Attribute Error") def selectBestOpportunity(self, market1, market2, minPercent=0.45): opportunitiesList = [] while opportunitiesList == []: opportunitiesList = self.arbitrageScan(market1, market2, minPercent) if len(opportunitiesList) != 0: bestOpportunity = opportunitiesList[0] for opportunity in opportunitiesList: if bestOpportunity[2] < opportunity[2]: bestOpportunity = opportunity else: print("No Opportunities Found") bestOpportunity = ("", "", 0.0, 0) return bestOpportunity def activateArbitrage(self, market1, market2, minPercent=0.45): bestArbitrageOpportunity = self.selectBestOpportunity( market1, market2, minPercent) coinName = str(bestArbitrageOpportunity[0]).replace("BTC-", "") if bestArbitrageOpportunity[1] == 'Market1to2': fullTopBuyOrder = self.getTopOrder(market1, bestArbitrageOpportunity[0], False) btcBuyOrderAvailable = (float(fullTopBuyOrder[0]) * float(fullTopBuyOrder[1])) btcBalanceOnMarket = float( self.getCurrentBalance('poloniex', "BTC")) if float(btcBuyOrderAvailable) > float(btcBalanceOnMarket): btcBuyOrderAvailable = float(btcBalanceOnMarket) coinAvailable = float(btcBuyOrderAvailable) / float( fullTopBuyOrder[0]) if market1 == "poloniex" or market1 == "Poloniex": try: if float( self.getTopOrder( market1, bestArbitrageOpportunity[0], False, 0)[0]) * float( self.getTopOrder( market1, bestArbitrageOpportunity[0], False, 0)[1]) < float( self.getBalance('poloniex', 'BTC')): self.poloniexBot.buy( bestArbitrageOpportunity[0].replace("-", "_"), fullTopBuyOrder[0], coinAvailable) print( "Successfully Bought on Poloniex, Attempting to Send to Bittrex Now..." ) time.sleep(3) self.poloniexBot.withdraw( coinName, (self.getCurrentBalance('poloniex', coinName)), self.getWalletAddress('bittrex', coinName)) tempCounter = 0 print(self.getCurrentBalance('bittrex', coinName)) while float(self.getCurrentBalance( 'bittrex', coinName)) < 0.0005: time.sleep(5) tempCounter = tempCounter + 1 if tempCounter > 15: print("Still Awaiting Deposit...") tempCounter = 0 print( "Deposit Confirmed & Active! Preparing to Dump in 5 Seconds" ) time.sleep(5) while float(self.getCurrentBalance(market2, coinName) ) > 0.00050055 or self.getCurrentBalance( market2, coinName) == None: time.sleep(3) self.bittrexBot.sell_limit( bestArbitrageOpportunity[0], self.getCurrentBalance('bittrex', coinName), self.getTopOrder(market2, bestArbitrageOpportunity[0], True, 1)) print( "Finished Selling All the Coins that Could be Sold. Cycle Complete." ) else: print( "The order didnt stay high enough, starting over") self.activateArbitrage(market1, market2, minPercent) except MemoryError: print("Error") if bestArbitrageOpportunity[1] == 'Market2to1': fullTopBuyOrder = self.getTopOrder(market2, bestArbitrageOpportunity[0], False, 0) btcBuyOrderAvailable = (float(fullTopBuyOrder[0]) * float(fullTopBuyOrder[1])) btcBalanceOnMarket = float(self.getCurrentBalance(market2, "BTC")) if btcBuyOrderAvailable > btcBalanceOnMarket: btcBuyOrderAvailable = btcBalanceOnMarket coinAvailable = float(btcBuyOrderAvailable) / float( fullTopBuyOrder[0]) if market2 == "bittrex" or market2 == "Bittrex": try: if float( self.getTopOrder( market1, bestArbitrageOpportunity[0], False, 0)[0]) * float( self.getTopOrder( market1, bestArbitrageOpportunity[0], False, 0)[1]) < float( self.getCurrentBalance( 'bittrex', 'BTC')): print("Buying " + str(bestArbitrageOpportunity[0]) + " " + str(coinAvailable)) buy = self.bittrexBot.buy_limit( bestArbitrageOpportunity[0], coinAvailable, fullTopBuyOrder[0]) print(buy) time.sleep(5) if buy['success'] == True: print( "Successfully Bought on Bittrex, Attempting to Send to Poloniex Now..." ) time.sleep(5) self.bittrexBot.withdraw( coinName, self.getCurrentBalance(market2, coinName), self.getWalletAddress(market1, coinName)) tempCounter = 0 print(self.getCurrentBalance(market1, coinName)) while float( self.getCurrentBalance(market1, coinName) ) < 0.00050055 or self.getCurrentBalance( market1, coinName) == None: time.sleep(5) tempCounter = tempCounter + 1 if tempCounter > 15: print("Still Awaiting Deposit...") tempCounter = 0 print( "Deposit Confirmed and Active! Preparing to Dump in 5 Seconds" ) time.sleep(5) while float( self.getCurrentBalance( market1, coinName)) > 0.00010055: time.sleep(5) self.poloniexBot.sell( str(bestArbitrageOpportunity[0]).replace( "-", "_"), float( self.getTopOrder( market1, bestArbitrageOpportunity[0]. replace("-", "_"), True, 1)), self.getCurrentBalance(market1, coinName)) print( "Attempting to Sell Maximum Amount of Coins that Could be Sold." ) print("Finished Selling all coins. Cycle Complete") else: print("Failed to Buy") return "Failed to Buy" else: print( "The order didn't stay high enough, starting over") self.activateArbitrage(market1, market2, minPercent) except AttributeError: print("Attribute Error, sorry") def getLendingBalances(self): #Only works with Poloniex try: return cryptoCommander.poloniexBot.api_query( 'returnAvailableAccountBalances')['lending'] except KeyError: return [] def getCurrentLoanOffers(self, coin): #Only works with Poloniex ret = urllib2.request.urlopen('http://poloniex.com/public?command=' + 'returnLoanOrders' + '¤cy=' + str(coin)) return json.loads(ret.read()) def getPrimeLendingRate(self, coin, minWeight=Decimal('25.0')): #Only works with Poloniex accumulatedWeight, bestRate = Decimal('0.0'), Decimal('0.0') print(accumulatedWeight) for offer in self.getCurrentLoanOffers(coin)['offers']: if accumulatedWeight < minWeight: print('Accumulated weight is less than 25: ' + str(accumulatedWeight)) accumulatedWeight = accumulatedWeight + Decimal( str(offer['amount'])) else: print('Best rate is: ' + str(offer['rate'])) bestRate = Decimal(str(offer['rate'])) - Decimal('0.000001') break if bestRate < Decimal('0.000001'): bestRate = Decimal('0.000001') return bestRate def getActiveLoans(self): #Only works with Poloniex return self.poloniexBot.api_query('returnActiveLoans') def getOpenLoanOffers(self): #Only works with Poloniex try: return self.poloniexBot.api_query('returnOpenLoanOffers') except KeyError: return [] def cancelLoanOffer(self, currency, orderNumber): #Only works with Poloniex return self.poloniexBot.api_query('cancelLoanOffer', { "currency": currency, "orderNumber": orderNumber }) def cancelAllLoanOffers(self): openLoansDict = self.getOpenLoanOffers() for openLoanCoin in openLoansDict: for dataObject in openLoansDict[openLoanCoin]: self.cancelLoanOffer(openLoanCoin, dataObject[id]) def createLoanOffer(self, currency, amount, duration, autoRenew, lendingRate): return self.poloniexBot.api_query( 'createLoanOffer', { "currency": currency, "amount": amount, "duration": duration, "autoRenew": autoRenew, "lendingRate": lendingRate, }) def checkLendingStagnation(self): openLoansDict = self.getOpenLoanOffers() for openLoanCoin in openLoansDict: for data in openLoansDict[openLoanCoin]: if (datetime.datetime.utcnow() - datetime.datetime.strptime( str(data['date']), '%Y-%m-%d %X') > datetime.timedelta(minutes=2)): print('Cancelling Loan Orders that are stagnant.') self.cancelLoanOffer(openLoanCoin, data['id']) def placeAllLoans(self): balances = self.getLendingBalances() for coin in balances: try: print(balances[coin]) if type(balances[coin] ) != Decimal and balances[coin] > Decimal('0.0'): balances[coin] = Decimal(str(balances[coin])) if type(balances[coin] ) == Decimal and balances[coin] >= Decimal('0.01'): #print "Print currency available is: " + str(balances[coin]) + str(coin) + ", Lending Now." while Decimal(str(balances[coin])) >= Decimal('0.01'): if Decimal(str(balances[coin])) <= Decimal( '0.02') and Decimal(str( balances[coin])) >= Decimal('0.01'): print('lending between 0.01 and 0.02') print( self.createLoanOffer( coin, float(balances[coin]), 2, 0, self.getPrimeLendingRate(coin))) else: primeRate = self.getPrimeLendingRate(coin) print("Prime Rate is: " + str(primeRate)) if primeRate <= Decimal('0.000025') or Decimal( balances[coin]) > Decimal('0.1'): if Decimal(balances[coin]) >= Decimal('10.0'): if Decimal( balances[coin] ) < Decimal('20.0') and Decimal( balances[coin]) > Decimal('10.0'): print('lending between 10 and 20') print( self.createLoanOffer( coin, float(balances[coin]), 2, 0, primeRate)) else: print('lending 10') print( self.createLoanOffer( coin, 10.0, 2, 0, primeRate)) else: if Decimal( balances[coin]) > Decimal('0.1'): if Decimal(balances[coin]) < Decimal( '0.2') and Decimal( balances[coin]) > Decimal( '0.1'): print( 'lending between 0.1 and 0.2') print( self.createLoanOffer( coin, float(balances[coin]), 2, 0, primeRate)) else: print('lending 0.1') print( self.createLoanOffer( coin, 0.1, 2, 0, primeRate)) else: print('lending 0.01') print( self.createLoanOffer( coin, 0.01, 2, 0, primeRate)) else: print('lending 0.01') print( self.createLoanOffer( coin, 0.01, 2, 0, primeRate)) time.sleep(.2) balances = self.getLendingBalances() else: print('No coins available to lend, sorry!') except KeyError: print('All loans for ' + str(coin) + ' actively being lent.') def startLendingAutomation(self): while True: try: while self.getLendingBalances( ) != None and self.getOpenLoanOffers() != None: while any(self.getLendingBalances()) > Decimal( '0.001') or any(self.getOpenLoanOffers()): self.placeAllLoans() time.sleep(150) self.checkLendingStagnation() print('All Done.') except TypeError: print("NOT done")
print("Set sell percent ->\t\t", cfg.getfloat('Data', 'sellPercent'), "%") print("Set commission ->\t\t", cfg.getfloat('Data', 'commission'), "%") print("Set bot owner ->\t\t", cfg.get('Data', 'owner')) getMe = bot.getMe() if getMe != True: getMeStatus = 'OK!' userName = getMe['result']['username'] else: getMeStatus = 'FAIL!' userName = getMe time.sleep(30) quit() print("Init bot status ->\t\t", getMeStatus, '->\t', userName) balance = my_bittrex.get_balance('BTC') balanceStatus = balance['success'] if balanceStatus == True: balanceStatus = 'OK!' else: balanceStatus = 'FAIL!' print( "Init bittrex status ->\t", balanceStatus, '->\t', "Available BTC for trading -> %(sum).8f" % {'sum': balance['result']['Available']}) print("TeleTradingBittrex_bot started\t OK!") print() # Цикл для проверки новых сообщений while True: