class Liqui: def __init__(self, key, secret): self.logger = Logger(__name__) try: self.client = Client(key, secret) except Exception as e: self.logger.log(e) raise ExchangeException(self.__class__.__name__, e) def getBalances(self): try: result = self.client.balances() balances = {} for currency in result.keys(): name = currency.upper() value = float(result[currency]) if value > Config.BALANCE_ZERO: balances[name] = value return balances except Exception as e: self.logger.log(e) raise ExchangeException(self.__class__.__name__, e)
def __init__(self, key, secret): self.logger = Logger(__name__) try: self.client = Client(key, secret) except Exception as e: self.logger.log(e) raise ExchangeException(self.__class__.__name__, e)
def __init__(self): self.liqui = Liqui(settings.LIQUI.API_KEY, settings.LIQUI.API_SECRET) self.binance = Client(settings.BINANCE.API_KEY, settings.BINANCE.API_SECRET) self.markets = { 'LIQUI': ccxt.liqui({ 'apiKey': settings.LIQUI.API_KEY, 'secret': settings.LIQUI.API_SECRET }), 'BINANCE': ccxt.binance({ 'apiKey': settings.BINANCE.API_KEY, 'secret': settings.BINANCE.API_SECRET }) } self.minimum_order = settings.MINIMUM_AMOUNT_TO_TRADE
def __init__(self): self.liqui = Liqui(settings.LIQUI.API_KEY, settings.LIQUI.API_SECRET) self.binance = Client(settings.BINANCE.API_KEY, settings.BINANCE.API_SECRET) self.markets = { 'LIQUI': ccxt.liqui({ 'apiKey': settings.LIQUI.API_KEY, 'secret': settings.LIQUI.API_SECRET, 'timeout': settings.LIQUI.TIMEOUT }), 'BINANCE': ccxt.binance({ 'apiKey': settings.BINANCE.API_KEY, 'secret': settings.BINANCE.API_SECRET, 'timeout': settings.BINANCE.TIMEOUT }) } # Init markets for key, value in self.markets.items(): value.load_markets()
class Liqui: def __init__(self, key, secret): self.client = Client(key, secret) self.logger = Logger(__name__) def getBalances(self): try: result = self.client.balances() balances = {} for currency in result.keys(): name = currency.encode('utf-8').upper() value = float(result[currency]) if value > 0.0: balances[name] = value return balances except Exception as e: self.logger.log(e) raise ExchangeException(self.__class__.__name__, e.message)
def __init__(self, key, secret): self.client = Client(key, secret) self.logger = Logger(__name__)
class Trader(object): _sleep_time = 5 _pair = "{}/ETH" _LIMIT = "limit" def __init__(self): self.liqui = Liqui(settings.LIQUI.API_KEY, settings.LIQUI.API_SECRET) self.binance = Client(settings.BINANCE.API_KEY, settings.BINANCE.API_SECRET) self.markets = { 'LIQUI': ccxt.liqui({ 'apiKey': settings.LIQUI.API_KEY, 'secret': settings.LIQUI.API_SECRET, 'timeout': settings.LIQUI.TIMEOUT }), 'BINANCE': ccxt.binance({ 'apiKey': settings.BINANCE.API_KEY, 'secret': settings.BINANCE.API_SECRET, 'timeout': settings.BINANCE.TIMEOUT }) } # Init markets for key, value in self.markets.items(): value.load_markets() @staticmethod def new_exposure(exposure): current_profit = exposure - 1 minimum_profit = settings.PROFIT_FACTOR - 1 new_profit = current_profit * ( 1 - settings.PROFIT_REDUCTION / minimum_profit) new_exposure = round(1 + new_profit, 6) logger.info("New exposure: {}".format(new_exposure)) return new_exposure @staticmethod def profit_reduction(exposure): current_profit = exposure - 1 minimum_profit = settings.PROFIT_FACTOR - 1 reduction = round( current_profit * settings.PROFIT_REDUCTION / minimum_profit, 10) logger.info("Profit reduction: {}".format(reduction)) return reduction @staticmethod def fill_buy_sell_order(order, market): return Order(market, order.get('id'), Analyser.extract_type(order, market), Analyser.extract_start_amount(order, market), Analyser.extract_remaining_amount2(order, market), Analyser.extract_price2(order, market), Analyser.extract_status(order, market)) @staticmethod def fill_fetch_order(order, market): return Order(market, order.get('id'), Analyser.extract_type(order, market), Analyser.extract_start_amount(order, market), Analyser.extract_remaining_amount_order(order, market), Analyser.extract_price2(order, market), Analyser.extract_status_order(order, market)) def buy(self, market, coin, volume, rate): symbol = self._pair.format(coin) volume = self.markets.get(market).amount_to_lots(symbol, volume) return self.markets.get(market).create_order(symbol, self._LIMIT, 'buy', volume, rate) def sell(self, market, coin, volume, rate): symbol = self._pair.format(coin) volume = self.markets.get(market).amount_to_lots(symbol, volume) return self.markets.get(market).create_order(symbol, self._LIMIT, 'sell', volume, rate) def cancel_order(self, market, coin, order_id): symbol = self._pair.format(coin) return self.markets.get(market).cancel_order(order_id, symbol) def fetch_order(self, market, coin, order_id): symbol = self._pair.format(coin) return self.markets.get(market).fetch_order(order_id, symbol) def buy_coin(self, coin, market, amount, price): # Temporary origin market checking until abstracted if market == "LIQUI": pair = "{}_eth".format(coin).lower() order = self.liqui.buy(pair, price, amount) order_id = order.get("order_id") elif market == "BINANCE": symbol = "{}ETH".format(coin) else: logger.error("Unknown market: {}".format(market)) return -1 logger.info("Buying {} {} at {} on {}. ID: {}".format( amount, coin, price, market, order_id)) return order_id def sell_coin(self, coin, market, amount, price): # Temporary origin market checking until abstracted if market == "LIQUI": pair = "{}_eth".format(coin).lower() order = self.liqui.sell(pair, price, amount) order_id = order.get("order_id") elif market == "BINANCE": symbol = "{}ETH".format(coin) else: logger.error("Unknown market: {}".format(market)) return -1 logger.info("Selling {} {} at {} on {}. ID: {}".format( amount, coin, price, market, order_id)) return order_id def wait_for_order(self, order_id, market, timeout=300): completed = False while not completed: timeout -= self._sleep_time time.sleep(self._sleep_time) if timeout <= 0: logger.error( "Order {} is taking too long to complete".format(order_id)) return False # Temporary origin market checking until abstracted if market == "LIQUI": order_info = self.liqui.order_info(order_id) status = order_info.get(order_id).get("status") if status != 0: completed = True elif market == "BINANCE": pass else: logger.error("Unknown market: {}".format(market)) return False logger.info("Order {} completed".format(order_id)) return True
class Analyser(object): _pair = "{}/ETH" _LIMIT = "limit" def __init__(self): self.liqui = Liqui(settings.LIQUI.API_KEY, settings.LIQUI.API_SECRET) self.binance = Client(settings.BINANCE.API_KEY, settings.BINANCE.API_SECRET) self.markets = { 'LIQUI': ccxt.liqui({ 'apiKey': settings.LIQUI.API_KEY, 'secret': settings.LIQUI.API_SECRET }), 'BINANCE': ccxt.binance({ 'apiKey': settings.BINANCE.API_KEY, 'secret': settings.BINANCE.API_SECRET }) } self.minimum_order = settings.MINIMUM_AMOUNT_TO_TRADE def get_coin_analysis(self, coin, origin, destination): coin_analysis = CoinAnalysis(coin=coin, origin=origin, destination=destination) # Temporary origin market checking until abstracted if origin == "LIQUI": pair = "{}_eth".format(coin).lower() origin_ticker = self.liqui.ticker(pair) origin_last_price = origin_ticker.get(pair).get('last') elif origin == "BINANCE": symbol = "{}ETH".format(coin) origin_ticker = self.binance.get_ticker(symbol=symbol) origin_last_price = float(origin_ticker.get('lastPrice')) else: logger.error("Unknown origin market: {}".format(origin)) return coin_analysis coin_analysis.origin_price = origin_last_price logger.debug("Last price for origin market {} is {:.7f}".format( origin, origin_last_price)) # Temporary destination market checking until abstracted if destination == "LIQUI": pair = "{}_eth".format(coin).lower() destination_ticker = self.liqui.ticker(pair) destination_last_price = destination_ticker.get(pair).get('last') elif destination == "BINANCE": symbol = "{}ETH".format(coin) destination_ticker = self.binance.get_ticker(symbol=symbol) destination_last_price = float(destination_ticker.get('lastPrice')) else: logger.error("Unknown destination market: {}".format(origin)) return coin_analysis coin_analysis.destination_price = destination_last_price logger.debug("Last price for destination market {} is {:.7f}".format( destination, destination_last_price)) coin_analysis.profit_factor = round( destination_last_price / origin_last_price, 6) logger.debug("Profit Factor: {}".format(coin_analysis.profit_factor)) return coin_analysis async def get_latest_depth(self, market, coin, params={}): return await self.markets.get(market).fetch_order_book( self._pair.format(coin), params=params) async def get_balance(self, market, params={}): return await self.markets.get(market).fetch_balance(params=params) def is_order_filled(self, order, order_id, market): """ Use this method when parsing the result of an order fetch :param order: :param order_id: :param market: :return: """ # TODO: Refactor to add markets more easily if market == "LIQUI": if order.get("info").get("return").get( str(order_id)).get("status") == 1: return True elif market == "BINANCE": if order.get("info").get("status") == "FILLED": return True else: logger.error("Cannot extract status for market {}".format(market)) return False def extract_amount(self, order, market): # TODO: Refactor to add markets more easily if market == "LIQUI": return order.get("info").get("return").get("received") elif market == "BINANCE": return float(order.get("info").get("executedQty")) else: logger.error("Cannot extract status for market {}".format(market)) return 0 def extract_remaining_amount(self, order, market): # TODO: Refactor to add markets more easily if market == "LIQUI": return order.get("info").get("return").get("remains") elif market == "BINANCE": price = float(order.get("info").get("origQty")) - float( order.get("info").get("executedQty")) logger.debug(price) return price else: logger.error( "Cannot remaining amount for market {}".format(market)) return 0 def extract_order_executed_amount(self, order, order_id, market): # TODO: Refactor to add markets more easily if market == "LIQUI": return order.get("info").get("return").get( str(order_id)).get("amount") elif market == "BINANCE": return float(order.get("info").get("executedQty")) else: logger.error("Cannot executed amount for market {}".format(market)) return 0 def extract_price(self, order, market): # TODO: Refactor to add markets more easily if market == "LIQUI": return order.get("price") elif market == "BINANCE": return float(order.get("info").get("price")) else: logger.error("Cannot extract status for market {}".format(market)) return 0 @staticmethod def extract_type(order, market): if market == "LIQUI": return Types[order.get("side").upper()] elif market == "BINANCE": return Types[order.get("info").get("side")] else: logger.error("Cannot extract type for market {}".format(market)) return Types.UNKNOWN @staticmethod def extract_start_amount(order, market): if market == "LIQUI": return order.get("amount") elif market == "BINANCE": return float(order.get("info").get("origQty")) else: logger.error( "Cannot extract start amount for market {}".format(market)) return 0 @staticmethod def extract_remaining_amount2(order, market): if market == "LIQUI": return order.get("info").get("return").get("remains") elif market == "BINANCE": return float(order.get("info").get("origQty")) - float( order.get("info").get("executedQty")) else: logger.error( "Cannot extract remaining amount for market {}".format(market)) return 0 @staticmethod def extract_remaining_amount_order(order, market): if market == "LIQUI": return order.get("info").get("amount") elif market == "BINANCE": return float(order.get("info").get("origQty")) - float( order.get("info").get("executedQty")) else: logger.error( "Cannot extract remaining amount for market {} (order)".format( market)) return 0 @staticmethod def extract_price2(order, market): if market == "LIQUI": return order.get("price") elif market == "BINANCE": return float(order.get("info").get("price")) else: logger.error("Cannot extract price for market {}".format(market)) return 0 @staticmethod def extract_status(order, market): if market == "LIQUI": if order.get("info").get("return").get("order_id") == 0: return Status.DONE else: return Status.ONGOING elif market == "BINANCE": if order.get("info").get("status") == "FILLED": return Status.DONE else: return Status.ONGOING else: logger.error("Cannot extract status for market {}".format(market)) return Status.UNKNOWN @staticmethod def extract_status_order(order, market): if market == "LIQUI": return { 0: Status.ONGOING, 1: Status.DONE, 2: Status.CANCELLED, 3: Status.CANCELLED }[order.get("info").get("status")] elif market == "BINANCE": return { 'NEW': Status.ONGOING, 'PARTIALLY_FILLED': Status.ONGOING, 'FILLED': Status.DONE, 'CANCELED': Status.CANCELLED }[order.get("info").get("status")] else: logger.error( "Cannot extract status for market {} (order)".format(market)) return Status.UNKNOWN @staticmethod def is_filled(order, market): if Analyser.extract_status(order, market) == Status.DONE: return True else: return False def extract_good_order(self, orders): for order in orders: if order[0] * order[1] > self.minimum_order: return order logger.error("No good order found") return [orders[0][0], 0]