Esempio n. 1
0
class BittrexUtils:
    def __init__(self):
        self.my_bittrex = Bittrex(BITTREX_KEY, BITTREX_SECRET)

    def get_available_balance(self, symbol):
        return self.my_bittrex.get_balance(symbol)["result"]["Available"]

    def get_ask(self, symbol):
        """Return current ask price for symbol"""
        pair = f'BTC-{symbol}'
        return self.my_bittrex.get_marketsummary(pair)["result"][0]["Ask"]

    def get_bid(self, symbol):
        """Return current bid price for symbol"""
        pair = f'BTC-{symbol}'
        return self.my_bittrex.get_marketsummary(pair)["result"][0]["Bid"]

    def get_last(self, symbol):
        """Return current last price for symbol"""
        pair = f'BTC-{symbol}'
        return self.my_bittrex.get_marketsummary(pair)["result"][0]["Last"]

    def prepare_btc_buy(self, symbol, amount):
        """Prepare get pair, quantity and price for create_buy_order"""
        pair = f'BTC-{symbol}'
        price = self.get_ask(symbol) * 1.02  # Buy 2% higher
        quantity = round(amount / price, 8)
        return pair, quantity, price

    def create_buy_order(self, pair, quantity, price):
        """Create buy order on Bittrex, return order uuid"""
        response = self.my_bittrex.buy_limit(pair, quantity, price)
        if response["success"]:
            return response["result"]["uuid"]
        else:
            raise Exception(response["message"])

    def create_sell_order(self, pair, quantity, price):
        """Create sell order on Bittrex, return order uuid"""
        response = self.my_bittrex.sell_limit(pair, quantity, price)
        if response["success"]:
            return response["result"]["uuid"]
        else:
            raise Exception(response["message"])

    def get_open_orders(self):
        orders = self.my_bittrex.get_open_orders()["result"]
        result = []
        for order in orders:
            message = f'Order {order["OrderUuid"]}\n\n{order["Exchange"]}\nType: {order["OrderType"]}\nQuantity: {order["Quantity"]}\nPrice: {order["Limit"]}\nBTC total: {order["Limit"]*order["Quantity"]}\n\nOpen: {order["Closed"] == None}'
            result.append(message)
        return result

    def cancel_order(self, uuid):
        return self.my_bittrex.cancel(uuid)["success"]

    def get_order_status(self, uuid):
        """Returns string of order status"""
        order = self.my_bittrex.get_order(uuid)["result"]
        return f'Order {order["OrderUuid"]}\n\n{order["Exchange"]}\nType: {order["Type"]}\nQuantity: {order["Quantity"]}\nPrice: {order["Limit"]}\nBTC total: {order["Reserved"]}\n\nOpen: {order["IsOpen"]}'
Esempio n. 2
0
class Transaction(object):
    def __init__(self, market, quantity=0, rate=0):
        self.client = Bittrex(API_KEY, API_SECRET)
        self.market = market
        self.quantity = quantity
        self.rate = rate

    def createBuyOrder(self):

        orderData = self.client.buy_limit(self.market, self.quantity,
                                          self.rate)
        self.uuid = self.orderData.get('result').get('uuid')

    def createSellOrder(self):

        orderData = self.client.sell_limit(self.market, self.quantity,
                                           self.rate)
        self.uuid = self.orderData.get('result').get('uuid')

    def cancelBuyOrder(self):
        self.client.cancel(self.uuid)

    def cancelSellOrder(self):
        self.client.cancel(self.uuid)

    def verifyOrderCompletion(self):
        if self.client.get_order(
                self.uuid).get('result').get('IsOpen') == False:
            return True
        else:
            return False
Esempio n. 3
0
    def PlaceBuyOrder(self, market, quantity, rate):
        BittRexCo = Bittrex(self.apikey, self.apisecret)
        Data = BittRexCo.buy_limit(market, quantity, rate)

        if not Data['success']:
            print(Data['message'])

        return Data['success']
Esempio n. 4
0
def bittrex_buy_limit(chat_id, **params):
	full_api = getbittrexapi(chat_id)['bittrex_api']
	api_key = full_api.split(':')[0].strip()
	api_secret = full_api.split(':')[1].strip()
	client = Bittrex(api_key, api_secret, api_version=API_V1_1)

	try:
		result = client.buy_limit(**params)
		print(result)
		return result
	except Exception as e:
		print(e)
Esempio n. 5
0
from bittrex.bittrex import Bittrex

bit = Bittrex(api_key='748fdc31633644849231b13a9f2cafdd', api_secret='25e3129bc6ed4cf3b3d7beaebfc4914e')

# Only one instance is ok

# Function get_markets

#market_list = bit.get_markets()
# Uncomment next line to print
# print(market_list)

# Ticker list example

#firs_market = market_list['result'][0]['MarketName']
#ticker_for_the_first_market = bit.get_ticker('BTC-CRAVE')

#print (ticker_for_the_first_market)

# Buy limit example
limit = bit.buy_limit('BTC-CRAVE', float(0.1) , float(2.1))
print(limit)
Esempio n. 6
0
class BittrexClient(Base):
    """
    Bittrex interface
    """
    arg_parser = configargparse.get_argument_parser()
    arg_parser.add('--bittrex_api_key', help='Bittrex API key')
    arg_parser.add("--bittrex_secret", help='Bittrex secret key')
    arg_parser.add("--bittrex_txn_fee", help='Bittrex txn. fee')
    open_orders = []

    def __init__(self):
        args = self.arg_parser.parse_known_args()[0]
        super(BittrexClient, self).__init__()
        api_key = args.bittrex_api_key
        secret = args.bittrex_secret
        self.transaction_fee = float(args.bittrex_txn_fee)
        self.bittrex = Bittrex(api_key, secret)
        self.pair_delimiter = '-'
        self.verbosity = args.verbosity

    def get_pairs(self):
        """
        Returns ticker pairs for all currencies
        """
        markets = self.bittrex.get_market_summaries()
        if markets is None:
            print(colored('\n! Got empty markets', 'red'))
            return None

        res = markets['result']
        pairs = []
        for market in res:
            pair = market['MarketName']
            # pair = pair.replace('-', '_')
            pairs.append(pair)
        return pairs

    def get_candles_df(self,
                       currency_pair,
                       epoch_start,
                       epoch_end,
                       interval_in_sec=300):
        """
        Returns candlestick chart data in pandas dataframe
        """
        dict_data = self.get_candles(currency_pair, epoch_start, epoch_end,
                                     interval_in_sec)
        df = pd.DataFrame(dict_data)
        df['pair'] = currency_pair
        return df

    def get_candles(self,
                    currency_pair,
                    epoch_start,
                    epoch_end,
                    interval_in_sec=300):
        """
        Returns candlestick chart data
        """
        currency_pair = currency_pair.replace('_', self.pair_delimiter)
        try:
            # tickInterval must be in [“oneMin”, “fiveMin”, “thirtyMin”, “hour”, “day”].
            res = self.bittrex.get_ticks(currency_pair,
                                         '“fiveMin”')  # era “fiveMin”
        except gaierror as e:
            print(
                colored(
                    '\n! Got gaierror exception from Bittrex client. Details: '
                    + e, 'red'))
            return dict()
        except Exception as e:
            print(
                colored('\n! Got exception from Bittrex client. Details: ' + e,
                        'red'))
            return dict()

        if res is None:
            print(
                colored('\n! Got empty result for pair: ' + currency_pair,
                        'red'))
            return dict()

        tickers = res['result']
        got_min_epoch_ticker = False
        raw_tickers = []

        if tickers is None:
            print(
                colored('\n! Got empty tickers for pair: ' + currency_pair,
                        'red'))
            return dict()

        # Parse tickers
        for ticker in tickers:
            naive_dt = parse(ticker['T'])
            utc_dt = naive_dt.replace(tzinfo=tzutc())
            epoch = int(utc_dt.timestamp())

            if epoch <= epoch_start:
                got_min_epoch_ticker = True

            # Skip/remove older than wanted tickers (adding extra hours to be sure that we have the data)
            if epoch < (epoch_start - 6 * 3600):
                continue

            raw_ticker = dict()
            raw_ticker['high'] = ticker['H']
            raw_ticker['low'] = ticker['L']
            raw_ticker['open'] = ticker['O']
            raw_ticker['close'] = ticker['C']
            raw_ticker['volume'] = ticker['V']
            raw_ticker['quoteVolume'] = ticker['BV']
            raw_ticker['date'] = epoch
            raw_ticker['weightedAverage'] = 0.0

            raw_tickers.append(raw_ticker)
        if not got_min_epoch_ticker:
            print(
                colored(
                    'Not able to get all data (data not available) for pair: '
                    + currency_pair, 'red'))

        # Create/interpolate raw tickers to fit our interval ticker
        out_tickers = []
        for ticker_epoch in range(epoch_start, epoch_end, interval_in_sec):
            items = [
                element for element in raw_tickers
                if element['date'] <= ticker_epoch
            ]
            if len(items) <= 0:
                print(
                    colored(
                        'Could not found a ticker for:' + currency_pair +
                        ', epoch:' + str(ticker_epoch), 'red'))
                continue
            # Get the last item (should be closest to search epoch)
            item = items[-1].copy()
            item['date'] = ticker_epoch
            out_tickers.append(item)
        return out_tickers.copy()
        # return self.bittrex.returnChartData(currency_pair, period, start, end)

    def get_balances(self):
        """
        Return available account balances (function returns ONLY currencies > 0)
        """
        resp = self.bittrex.get_balances()
        balances = resp['result']
        pairs = dict()
        for item in balances:
            currency = item['Currency']
            pairs[currency] = item['Available']

        return pairs

    @staticmethod
    def get_volume_from_history(history, candle_size):
        """
        Returns volume for given candle_size
        :param history: history data
        :param candle_size: in minutes
        :return: Calculated volume for given candle_size
        """
        volume = 0.0
        epoch_now = int(time.time())
        epoch_candle_start = epoch_now - candle_size * 60
        pattern = '%Y-%m-%dT%H:%M:%S'
        for item in history:
            time_string = item['TimeStamp'].split('.', 1)[0]
            dt = datetime.datetime.strptime(time_string, pattern)
            item_epoch = dt.replace(tzinfo=timezone.utc).timestamp()
            if item_epoch >= epoch_candle_start:
                quantity = item['Quantity']
                volume += quantity
        return volume

    def get_symbol_ticker(self, symbol, candle_size=5):
        """
        Returns real-time ticker Data-Frame
        :candle_size: size in minutes to calculate the interval
        """
        market = symbol.replace('_', self.pair_delimiter)

        ticker = self.bittrex.get_ticker(market)
        history = self.bittrex.get_market_history(market, 100)['result']
        volume = self.get_volume_from_history(history, candle_size)

        df = pd.DataFrame.from_dict(ticker['result'], orient="index")
        df = df.T
        # We will use 'last' price as closing one
        df = df.rename(columns={
            'Last': 'close',
            'Ask': 'lowestAsk',
            'Bid': 'highestBid'
        })
        df['volume'] = volume
        df['pair'] = symbol
        df['date'] = int(datetime.datetime.utcnow().timestamp())
        return df

    def get_market_history(self, start, end, currency_pair='all'):
        """
        Returns market trade history
        """
        logger = logging.getLogger(__name__)
        logger.warning('Not implemented!')
        pass

    def trade(self, actions, wallet, trade_mode):
        """
        Places actual buy/sell orders
        """
        if trade_mode == TradeMode.backtest:
            return Base.trade(actions, wallet, trade_mode)
        else:
            actions = self.life_trade(actions)
            return actions

    def life_trade(self, actions):
        """
        Places orders and returns order number
        """
        for action in actions:
            market = action.pair.replace('_', self.pair_delimiter)

            # Handle buy/sell mode
            wallet = self.get_balances()
            if action.buy_sell_mode == BuySellMode.all:
                action.amount = self.get_buy_sell_all_amount(wallet, action)
            elif action.buy_sell_mode == BuySellMode.fixed:
                action.amount = self.get_fixed_trade_amount(wallet, action)

            if self.verbosity:
                print(
                    'Processing live-action: ' + str(action.action) +
                    ', amount:',
                    str(action.amount) + ', pair:', market + ', rate:',
                    str(action.rate) + ', buy_sell_mode:',
                    action.buy_sell_mode)
            if action.action == TradeState.none:
                actions.remove(action)
                continue

            # If we don't have enough assets, just skip/remove the action
            if action.amount == 0.0:
                print(
                    colored(
                        'No assets to buy/sell, ...skipping: ' +
                        str(action.amount) + ' ' + market, 'green'))
                actions.remove(action)
                continue

            # ** Buy Action **
            if action.action == TradeState.buy:
                print(
                    colored(
                        'setting buy order: ' + str(action.amount) + '' +
                        market, 'green'))
                ret = self.bittrex.buy_limit(market, action.amount,
                                             action.rate)
                if not ret['success']:
                    print(
                        colored(
                            'Error: ' + ret['message'] + '. Txn: buy-' +
                            market, 'red'))
                    continue
                else:
                    uuid = ret['result']['uuid']
                    self.open_orders.append(uuid)
                    print(colored('Buy order placed (uuid): ' + uuid, 'green'))
                print(ret)

            # ** Sell Action **
            elif action.action == TradeState.sell:
                print(
                    colored(
                        'setting sell order: ' + str(action.amount) + '' +
                        market, 'yellow'))
                ret = self.bittrex.sell_limit(market, action.amount,
                                              action.rate)
                if not ret['success']:
                    print(
                        colored(
                            'Error: ' + ret['message'] + '. Txn: sell-' +
                            market, 'red'))
                    continue
                else:
                    uuid = ret['result']['uuid']
                    self.open_orders.append(uuid)
                    print(colored('Sell order placed (uuid): ' + uuid,
                                  'green'))
                print(ret)
        return actions

    def cancel_order(self, order_number):
        """
        Cancels order for given order number
        """
        return self.bittrex.cancel(order_number)

    def get_open_orders(self, currency_pair=''):
        """
        Returns open orders
        """
        return self.bittrex.get_open_orders(currency_pair)

    def get_trade_history(self, date_from, date_to, currency_pair='all'):
        """
        Returns trade history
        """
        # TODO
        pass
Esempio n. 7
0
class ApiWrapper(object):
    """
    Wrapper for exchanges.
    Currently implemented:
        * Bittrex
        * Poloniex (partly)
    """
    def __init__(self, config):
        """
        Initializes the ApiWrapper with the given config, it does not validate those values.
        :param config: dict
        """
        self.dry_run = config['dry_run']
        if self.dry_run:
            logger.info('Instance is running with dry_run enabled')

        use_poloniex = config.get('poloniex', {}).get('enabled', False)
        use_bittrex = config.get('bittrex', {}).get('enabled', False)

        if use_poloniex:
            self.exchange = Exchange.POLONIEX
            self.api = Poloniex(key=config['poloniex']['key'],
                                secret=config['poloniex']['secret'])
        elif use_bittrex:
            self.exchange = Exchange.BITTREX
            self.api = Bittrex(api_key=config['bittrex']['key'],
                               api_secret=config['bittrex']['secret'])
        else:
            self.api = None

    def buy(self, pair, rate, amount):
        """
        Places a limit buy order.
        :param pair: Pair as str, format: BTC_ETH
        :param rate: Rate limit for order
        :param amount: The amount to purchase
        :return: None
        """
        if self.dry_run:
            pass
        elif self.exchange == Exchange.POLONIEX:
            self.api.buy(pair, rate, amount)
            # TODO: return order id
        elif self.exchange == Exchange.BITTREX:
            data = self.api.buy_limit(pair.replace('_', '-'), amount, rate)
            if not data['success']:
                raise RuntimeError('BITTREX: {}'.format(data['message']))
            return data['result']['uuid']

    def sell(self, pair, rate, amount):
        """
        Places a limit sell order.
        :param pair: Pair as str, format: BTC_ETH
        :param rate: Rate limit for order
        :param amount: The amount to sell
        :return: None
        """
        if self.dry_run:
            pass
        elif self.exchange == Exchange.POLONIEX:
            self.api.sell(pair, rate, amount)
            # TODO: return order id
        elif self.exchange == Exchange.BITTREX:
            data = self.api.sell_limit(pair.replace('_', '-'), amount, rate)
            if not data['success']:
                raise RuntimeError('BITTREX: {}'.format(data['message']))
            return data['result']['uuid']

    def get_balance(self, currency):
        """
        Get account balance.
        :param currency: currency as str, format: BTC
        :return: float
        """
        if self.dry_run:
            return 999.9
        elif self.exchange == Exchange.POLONIEX:
            data = self.api.returnBalances()
            return float(data[currency])
        elif self.exchange == Exchange.BITTREX:
            data = self.api.get_balance(currency)
            if not data['success']:
                raise RuntimeError('BITTREX: {}'.format(data['message']))
            return float(data['result']['Balance'] or 0.0)

    def get_ticker(self, pair):
        """
        Get Ticker for given pair.
        :param pair: Pair as str, format: BTC_ETC
        :return: dict
        """
        if self.exchange == Exchange.POLONIEX:
            data = self.api.returnTicker()
            return {
                'bid': float(data[pair]['highestBid']),
                'ask': float(data[pair]['lowestAsk']),
                'last': float(data[pair]['last'])
            }
        elif self.exchange == Exchange.BITTREX:
            data = self.api.get_ticker(pair.replace('_', '-'))
            if not data['success']:
                raise RuntimeError('BITTREX: {}'.format(data['message']))
            return {
                'bid': float(data['result']['Bid']),
                'ask': float(data['result']['Ask']),
                'last': float(data['result']['Last']),
            }

    def cancel_order(self, order_id):
        """
        Cancel order for given order_id
        :param order_id: id as str
        :return: None
        """
        if self.dry_run:
            pass
        elif self.exchange == Exchange.POLONIEX:
            raise NotImplemented('Not implemented')
        elif self.exchange == Exchange.BITTREX:
            data = self.api.cancel(order_id)
            if not data['success']:
                raise RuntimeError('BITTREX: {}'.format(data['message']))

    def get_open_orders(self, pair):
        """
        Get all open orders for given pair.
        :param pair: Pair as str, format: BTC_ETC
        :return: list of dicts
        """
        if self.dry_run:
            return []
        elif self.exchange == Exchange.POLONIEX:
            raise NotImplemented('Not implemented')
        elif self.exchange == Exchange.BITTREX:
            data = self.api.get_open_orders(pair.replace('_', '-'))
            if not data['success']:
                raise RuntimeError('BITTREX: {}'.format(data['message']))
            return [{
                'id': entry['OrderUuid'],
                'type': entry['OrderType'],
                'opened': entry['Opened'],
                'rate': entry['PricePerUnit'],
                'amount': entry['Quantity'],
                'remaining': entry['QuantityRemaining'],
            } for entry in data['result']]

    def get_pair_detail_url(self, pair):
        """
        Returns the market detail url for the given pair
        :param pair: pair as str, format: BTC_ANT
        :return: url as str
        """
        if self.exchange == Exchange.POLONIEX:
            raise NotImplemented('Not implemented')
        elif self.exchange == Exchange.BITTREX:
            return 'https://bittrex.com/Market/Index?MarketName={}'.format(
                pair.replace('_', '-'))
Esempio n. 8
0
class BittrexService(ServiceInterface):
    name = 'bit'

    def __init__(self, **kwargs):
        api_key = kwargs["api_key"]
        api_secret = kwargs["api_secret"]

        if not all([api_key, api_secret]):
            raise Exception(
                f"Both api_key and api_secret are required for {name} exchange")

        self.client = Bittrex(api_key, api_secret, API_V1_1)
        self.debug_mode = environ.get("DEBUG", False)

    def get_account(self):
        return self.client.get_account()

    def buy(self, coin_name, quantity=None, pair_base="BTC", amount=None, order_type="market"):
        try:
            symbol = f"{pair_base}-{coin_name}"
            price = self.get_price(symbol)
            quantity = self.calculate_buy_qty(price, amount)

            logger.info(
                f"buy order request:{symbol}>price:{price}>quantity:{quantity} > order_type: {order_type}")

            if order_type.lower() == "market":
                order = self.client.buy_market(
                    market=symbol,
                    quantity=quantity)
            elif order_type.lower() == "market":
                order = self.client.buy_limit(
                    market=symbol,
                    quantity=quantity,
                    rate=price)

            logger.info(
                f"Bought order request:{symbol}>price:{price}>quantity:{quantity}> {order}")
            return order
        except Exception as ex:
            logger.error(ex, exc_info=True)
            raise UserAdviceException(ex)

    def sell(self, coin_name, quantity=None, pair_base="BTC", amount=None, order_type="market"):
        try:
            balance = self.get_balance(coin_name)
            if not balance:
                raise UserAdviceException(
                    f"Balance not enough to execute action in {name} exchange")

            symbol = f"{pair_base}-{coin_name}"
            price = self.get_price(symbol)
            quantity = self.calculate_sell_qty(price, amount)

            logger.info(
                f"sell order request:{symbol}>price:{price}>quantity:{quantity} > order_type: {order_type}")

            if order_type.lower() == "market":
                order = self.client.sell_market(
                    market=symbol,
                    quantity=quantity)
            elif order_type.lower() == "market":
                order = self.client.sell_limit(
                    market=symbol,
                    quantity=quantity,
                    rate=price)
            logger.info(
                f"Bought order request:{symbol}>price:{price}>quantity:{quantity}> {order}")
            return order
        except Exception as ex:
            logger.error(ex, exc_info=True)
            raise UserAdviceException(ex)

    def get_step_size(self, symbol):
        try:
            pass
        except Exception as ex:
            logger.error("Error retriving step size")
            return float(0.0)

    def get_price(self, symbol):
        try:
            price_info = self.client.get_ticker(market=symbol)
            logger.info(f"Price info: {price_info}")
            return float(price_info.get("price"))
        except Exception as ex:
            logger.error(ex, exc_info=True)
            raise Exception(ex)

    def calculate_sell_qty(self, price, amount, step_size=None):
        quantity = float(amount)/float(price)
        return float(quantity)

    def calculate_buy_qty(self, price, amount, step_size=None):
        quantity = float(amount)/float(price)
        return float(quantity)

    def get_balance(self, coin_name):
        pass
        try:
            balance_info = self.client.get_balance(coin_name)
            if not balance_info:
                raise UserAdviceException(
                    f"Coin not found in account in {self.name} exchange")
            if not balance_info.get("success"):
                raise Exception(balance_info.get("message"))
            result = balance_info.get("result")
            return float(result.get("Available"))
        except Exception as ex:
            logger.error(ex, exc_info=True)
            raise Exception(ex)

    def track_coin(self, payload):
        pass

    def get_prices(self):
        pass

    def get_symbol_info(self, coin_name, pair_base="BTC"):
        try:
            market = f"{pair_base}-{coin_name}"
            info = self.client.get_market_summary(market=market)
            logger.info(f"Symbol info: {info}")
            return info
        except Exception as ex:
            logger.error(ex, exc_info=True)
            raise Exception(ex)

    def get_open_orders(self, coin_name, pair_base="BTC"):
        try:
            market = f"{pair_base}-{coin_name}"
            orders = self.client.get_open_orders(market=market)
            logger.info(f"orders: {orders}")
            return orders
        except Exception as ex:
            logger.error(ex, exc_info=True)
            raise Exception(ex)

    def get_all_orders(self, coin_name, limit=5, pair_base="BTC"):
        try:
            market = f"{pair_base}-{coin_name}"
            orders = self.client.get_order_history(market=market, limit=limit)
            logger.debug(f"orders: {orders}")
            return orders
        except Exception as ex:
            logger.error(ex, exc_info=True)
            raise Exception(ex)
        # Initialize bittrex api
        api = Bittrex(API_KEY, API_SECRET, api_version=API_V1_1)

        # Open position logic:
        # 1. Get market last ask price
        r = api.get_ticker(market)
        if not r.get('success', False):
            raise Exception("Got an error while querying broker: %s" %
                            r.get('message', 'nd'))
        ticker = r.get('result')

        # 2. Buy with args.total value
        _quantity = args.total / ticker.get('Ask', 0)
        _rate = ticker.get('Ask', 0)
        r = api.buy_limit(market, quantity=_quantity, rate=_rate)
        if not r.get('success', False):
            raise Exception("Could not open position on broker: %s" %
                            r.get('message', 'nd'))

        open_order_id = r.get('result', {}).get('uuid', None)
    elif args.exchange == 'binance':
        market = "%s%s" % (args.market_currency, args.market_base)

        # Initialize binance api
        api = Binance(API_KEY, API_SECRET)

        # Is binance alive ?
        if api.get_system_status().get("status", -1) != 0:
            raise Exception("Exchange unavailable for trading")
Esempio n. 10
0
class BittrexApiClient(BaseTradeApiClient):

    PAIR_NAME_TEMPLATE = '{quote}-{base}'

    def __init__(self):
        super(BittrexApiClient, self).__init__()
        self.related_nodes = ['api3']
        self.api = self.get_api()

    def _get_api_currency_code(self, currency_code):
        return currency_code

    def _get_currency_by_api_code(self, api_currency_code):
        return Currency.objects.get(code=api_currency_code)

    def get_api_pairs_for_pair(self, pair):
        reverse_pair = pair.reverse_pair
        markets = self.get_all_active_pairs()
        for _pair in pair, reverse_pair:
            _name = self.get_api_pair_name(_pair)
            if _name in markets:
                return {
                    _pair: {
                        'api_pair_name':
                        _name,
                        'main_currency':
                        self._get_currency_by_api_code(markets[_name])
                    }
                }
        base_btc = Pair.objects.get(base=pair.base, quote__code='BTC')
        quote_btc = Pair.objects.get(base=pair.quote, quote__code='BTC')
        res = {}
        for _pair in base_btc, quote_btc:
            _name = self.get_api_pair_name(_pair)
            if _name in markets:
                res.update({
                    _pair: {
                        'api_pair_name':
                        _name,
                        'main_currency':
                        self._get_currency_by_api_code(markets[_name])
                    }
                })
        return res

    def get_api_pair_name(self, pair):
        return self.PAIR_NAME_TEMPLATE.format(
            base=self._get_api_currency_code(pair.base.code),
            quote=self._get_api_currency_code(pair.quote.code))

    def get_all_active_pairs(self):
        markets = self.api.get_markets().get('result', [])
        return {
            m.get('MarketName'): m.get('MarketCurrency')
            for m in markets if m['IsActive']
        }

    def get_api(self):
        if not self.api:
            self.api = Bittrex(settings.API3_KEY, settings.API3_SECRET)
        return self.api

    def get_balance(self, currency):
        raw_res = self.api.get_balance(
            self._get_api_currency_code(currency.code))
        result = raw_res.get('result', {})
        res = {
            key.lower(): Decimal(str(value if value else 0))
            for key, value in result.items()
            if key in ['Pending', 'Balance', 'Available']
        }
        return res

    def get_ticker(self, pair):
        market = self.PAIR_NAME_TEMPLATE.format(
            base=self._get_api_currency_code(pair.base.code),
            quote=self._get_api_currency_code(pair.quote.code))
        res = self.api.get_ticker(market)
        return res

    def get_rate(self, pair, rate_type='Ask'):
        ticker = self.get_ticker(pair)
        rate = ticker.get('result', {}).get(rate_type, 0)
        return Decimal(str(rate))

    def buy_limit(self, pair, amount, rate=None):
        market = self.PAIR_NAME_TEMPLATE.format(
            base=self._get_api_currency_code(pair.base.code),
            quote=self._get_api_currency_code(pair.quote.code))
        if not rate:
            rate = self.get_rate(pair, rate_type='Ask')
        res = self.api.buy_limit(market, amount, rate)
        trade_id = res.get('result', {}).get('uuid')
        return trade_id, res

    def sell_limit(self, pair, amount, rate=None):
        market = self.PAIR_NAME_TEMPLATE.format(
            base=self._get_api_currency_code(pair.base.code),
            quote=self._get_api_currency_code(pair.quote.code))
        if not rate:
            rate = self.get_rate(pair, rate_type='Bid')
        res = self.api.sell_limit(market, amount, rate)
        trade_id = res.get('result', {}).get('uuid')
        return trade_id, res

    def get_main_address(self, currency):
        raw_res = self.api.get_deposit_address(
            self._get_api_currency_code(currency.code))
        result = raw_res.get('result', {})
        address = result.get('Address', None)
        return address if address else None

    def release_coins(self, currency, address, amount):
        tx_id = None
        if isinstance(currency, Currency):
            currency = currency.code
        if isinstance(address, Address):
            address = address.address
        _currency = self._get_api_currency_code(currency)
        res = self.api.withdraw(_currency, amount, address)
        self.logger.info('Response from Bittrex withdraw: {}'.format(res))
        success = res.get('success', False)
        if success:
            tx_id = res.get('result', {}).get('uuid')
        return tx_id, success
Esempio n. 11
0
class BittrexBroker(BrokerBaseClass):
    """
    Inherits from alchemist_lib.broker.broker.BrokerBaseClass.

    Website: https://bittrex.com/

    Api documentation: https://bittrex.com/Home/Api

    Api wrapper: https://github.com/ericsomdahl/python-bittrex

    Attributes:
        session (sqlalchemy.orm.session.Session): Database connection.
        bittrex (bittrex.bittrex.Bittrex): Communication object.
    """
    def __init__(self, api_key=None, secret_key=None):
        """
        Costructor method.

        Args:
            api_key (str): The api key provided by Bittrex.
            secret_key (str): The secret key provided by Bittrex.

        Note:
            https://bittrex.com/Manage#sectionApi
            https://cryptocatbot.com/api-key-activation-exchanges/
        """

        BrokerBaseClass.__init__(self)
        self.bittrex = Bittrex(api_key=api_key,
                               api_secret=secret_key,
                               api_version=API_V1_1)

    def get_best_rate(self, asset, amount, field):
        """
        Bittrex doesn't allow to place market orders submitted via API so we need to get the best bid/ask price for every order.

        Args:
            asset (alchemist_lib.database.asset.Asset): The asset we want to exchange for BTC or vice versa.
            amount (decimal.Decimal): The amount we want to exchange.
            field (str): Must be "ask" or "bid".

        Return:
            price (decimal.Decimal): The best bid/ask, executing an order at this price is like submit a market order. If the book is too thin the return value is 0.
        """

        amount = abs(amount)
        pair = "BTC-{}".format(asset.ticker)
        if field == "ask":
            book = self.bittrex.get_orderbook(market=pair,
                                              depth_type=SELL_ORDERBOOK)
            if book["success"] == False or book["result"] == None:
                logging.debug(
                    "Bittrex api result is None or success is False. get_best_rate() method. Asset: {}"
                    .format(asset.ticker))
                return Decimal(0)

        else:
            book = self.bittrex.get_orderbook(market=pair,
                                              depth_type=BUY_ORDERBOOK)
            if book["success"] == False or book["result"] == None:
                logging.debug(
                    "Bittrex api result is None or success is False. get_best_rate() method. Asset: {}"
                    .format(asset.ticker))
                return Decimal(0)

        values = book["result"]

        orders_sum = Decimal(0)
        for book_item in values:
            orders_sum += Decimal(book_item["Quantity"])
            if orders_sum > amount:
                return Decimal(book_item["Rate"])

        return Decimal(0)

    def place_order(self, asset, amount, order_type):
        """
        Places an order for a specific asset on Bittrex.

        Args:
            asset (alchemist_lib.database.asset.Asset): The asset we want exchange for BTC.
            amount (decimal.Decimal): The amount we want to exchange.
            order_type (str): Type of order.

        Return:
            order_id (str, int): Order identifier, if some errors occur it returns int(-1).
        """

        pair = "BTC-{}".format(asset.ticker)

        min_order_size = BittrexExchange().get_min_order_size(asset=asset)
        logging.debug("Min order size for {} is {}".format(
            asset, min_order_size))

        if amount > min_order_size:
            field = "ask"
            operation = "buy"
        elif amount < (min_order_size * (-1)):
            field = "bid"
            operation = "sell"
        else:
            return -1

        if order_type == "MKT":
            rate = self.get_best_rate(asset=asset,
                                      amount=abs(amount),
                                      field=field)
        else:
            logging.critical("Unknown order type. NotImplemented raised.")
            raise NotImplemented("Unknown order type. NotImplemented raised.")

        logging.debug("Order: Pair: {}. Amount: {}. Operation: {}".format(
            pair, amount, operation))

        if operation == "buy":
            order_return_dict = self.bittrex.buy_limit(market=pair,
                                                       rate=rate,
                                                       quantity=amount)
        else:
            order_return_dict = self.bittrex.sell_limit(market=pair,
                                                        rate=rate,
                                                        quantity=abs(amount))

        if order_return_dict["result"] == None:
            logging.warning(
                "Bittrex api result is None or success is False. place_order() method. Order id will be -1. Asset: {}"
                .format(asset.ticker))
            return -1

        order_id = str(order_return_dict["result"]["uuid"])

        logging.info(
            "{} order placed for {}. Amount: {}. Order id: {}.".format(
                operation.upper(), asset.ticker, amount, order_id))
        print("{} order placed for {}. Amount: {}. Order id: {}.".format(
            operation.upper(), asset.ticker, amount, order_id))

        order = ExecutedOrder(order_id=order_id,
                              order_datetime=dt.datetime.utcnow(),
                              ticker=asset.ticker,
                              instrument_id=asset.instrument_id,
                              amount=amount,
                              operation=operation,
                              order_type=order_type,
                              broker_name="bittrex",
                              exchange_name="bittrex")

        self.session.add(order)
        self.session.commit()

        return order_id
                    amount_alis = islem_ucreti / bs  # alinacak coin miktari
                    amount_satis = amount_alis * 0.9975  # satilacak coin miktari

                    cuzdan_kontrol = 1
                except:
                    cuzdan_kontrol = 0
                    continue
            if cuzdan_kontrol == 1:
                if btrxavantaj > zorluk and btrx_wallet > islem_ucreti and polo_wallet_c * pa > islem_ucreti:
                    try:

                        pa = pa * (1 - (kayip + (btrxavantaj - zorluk)) / 1000)
                        bs = bs * (1 + (kayip + (btrxavantaj - zorluk)) / 1000)

                        polo.sell(poloniex_currency, pa, amount_satis)
                        order_s = my_bittrex.buy_limit(bittrex_currency,
                                                       amount_alis, bs)

                        print btrxavantaj, "\tBITTREX ALIS\t", bs, "\n\t\tPOLO SATIS\t", pa
                        print datetime.now().strftime('%Y-%m-%d %H:%M:%S')

                        # emir kontrolu. islem sonra devam edecek (bittrex)
                        while True:
                            try:
                                kontrol = my_bittrex.get_order(
                                    order_s['result']['uuid'])
                                if kontrol['result']['IsOpen'] == False:
                                    print "bittrex alim emri gerceklesti"

                                    break
                            except:
                                print "bittrex alim emir kontrol hatasi"
Esempio n. 13
0
def main():
    with open('./BittrexAPI.txt') as apifile:
        lines = apifile.readlines()
        my_api_key = lines[2]
        my_api_secret = lines[4]

    try:
        my_bittrex = Bittrex(my_api_key, my_api_secret, api_version='v1.1')
        print('API Logged In.')
    except:
        print('Login Error.')

    try:
        quantity = float(input('Set quantity as:'))
        aim = str(input('Set aim coin as:'))
    except:
        aim = None
        print('Input Error.')

    balance = my_bittrex.get_balance('BTC')
    if aim != None:
        buy_market = 'BTC-' + aim
        sell_market = aim + '-BTC'
    else:
        sys.exit()
    buy_rate = my_bittrex.get_ticker(buy_market)['result']['Bid']

    if quantity <= balance:
        start = time.time()
        buy_result = my_bittrex.buy_limit(buy_market, quantity, buy_rate)
        buy_uuid = buy_result['result']['uuid']
        if buy_result['success'] == True:
            end = time.time()
            print('Buying Has Done. Time: %s' % str(end - start))
        else:
            print('Buying Timeout.')
            my_bittrex.cancel(buy_uuid)
            sys.exit()

        sell_trig = str(input('Start Selling? (Y/N)'))
        if sell_trig != 'N':
            start = time.time()
            base_remain = my_bittrex.get_balance('BTC')
            aim_all = my_bittrex.get_balance(aim)
            sell_rate = my_bittrex.get_ticker(sell_market)['result']['Bid']
            if base_remain == balance - quantity:
                sell_result = my_bittrex.sell_limit(sell_market, aim_all,
                                                    sell_rate)
                if sell_result['success'] == True:
                    end = time.time()
                    print('Selling Has Done. Time: %s' % str(end - start))
                else:
                    print('Selling timeout.')
                    sys.exit()
            else:
                print('Buying delayed. Canceling Order.')
                my_bittrex.cancel(buy_uuid)
                sys.exit()
    else:
        print('Not Enough Funds.')
        sys.exit()
class BittrexService(Exchange):
    def __init__(self, name, public_key, private_key):
        Exchange.__init__(self, name)

        self.ob_ws = OrderBookSocket(self)
        self.ex_ws = ExecutionsSocket(self)
        self.ex_ws.authenticate(public_key, private_key)
        self.markets_following = {}
        self.open_orders = []
        self.rest_client = Bittrex(public_key,
                                   private_key,
                                   api_version=API_V1_1)

    def get_order_book(self, base, quote):
        resp = self.rest_client.get_orderbook(
            BittrexService._to_market(base, quote))
        print('rest book:' + str(resp['result']))
        if resp['success'] is True:
            book = resp['result']

            internal_book = {'bids': [], 'asks': []}

            for bid in book['buy']:
                internal_book['bids'].append(
                    [str(bid['Rate']), str(bid['Quantity'])])
            for ask in book['sell']:
                internal_book['asks'].append(
                    [str(ask['Rate']), str(ask['Quantity'])])

            internal_book['base'] = base
            internal_book['quote'] = quote
            internal_book['exchange'] = self.name

            self.notify_callbacks('order_book', data=internal_book)

            return internal_book

    def get_our_orders_by_decimal_price(self):
        our_orders_by_price = {'bids': {}, 'asks': {}}

        open_orders_copy = self.open_orders.copy()

        for order in open_orders_copy:
            order['price'] = Decimal(str(order['price']))
            order['quantity'] = Decimal(str(order['quantity']))
            order['cum_quantity_filled'] = Decimal(
                str(order['cum_quantity_filled']))
            if order['side'] == 'buy':
                if str(order['price']) not in our_orders_by_price['bids']:
                    our_orders_by_price['bids'][order['price']] = order[
                        'quantity'] - order['cum_quantity_filled']
                else:
                    our_orders_by_price['bids'][order['price']] += order[
                        'quantity'] - order['cum_quantity_filled']
            elif order['side'] == 'sell':
                if str(order['price']) not in our_orders_by_price['bids']:
                    our_orders_by_price['asks'][order['price']] = order[
                        'quantity'] - order['cum_quantity_filled']
                else:
                    our_orders_by_price['asks'][order['price']] += order[
                        'quantity'] - order['cum_quantity_filled']

        return our_orders_by_price

    def follow_market(self, base, quote):
        self.ob_ws.add_subscription(BittrexService._to_market(
            base, quote))  # bittrex has it backwards
        self.ex_ws.add_subscription(BittrexService._to_market(
            base, quote))  # bittrex has it backwards
        self.markets_following[self._to_market(base, quote)] = {
            'base': base,
            'quote': quote
        }

    def unfollow_market(self, base, quote):
        self.ob_ws.remove_subscription(BittrexService._to_market(base, quote))
        self.ex_ws.remove_subscription(BittrexService._to_market(base, quote))
        self.markets_following.pop(self._to_market(base, quote), None)

    @staticmethod
    def _to_market(base, quote):
        return quote + '-' + base

    def unfollow_all(self):
        markets = self.ob_ws.books_following.keys()

        for market in markets:
            self.ob_ws.remove_subscription(market)

    def get_balances(self):
        response = self.rest_client.get_balances()

        if response['success'] is True:
            internal_balances = []
            entries = response['result']
            for entry in entries:
                asset = entry['Currency']
                balance = Decimal(str(entry['Balance']))
                free = Decimal(str(entry['Available']))
                if balance > Decimal(0):
                    internal_balances.append({
                        'asset': asset,
                        'free': free,
                        'locked': balance - free
                    })

            self.notify_callbacks('account',
                                  account_type='balance',
                                  data=internal_balances)

            return internal_balances
        else:
            self.notify_callbacks('account',
                                  account_type='balances_failed',
                                  data={})
            return []

    def create_order(self,
                     base,
                     quote,
                     price,
                     quantity,
                     side,
                     order_type,
                     internal_order_id,
                     request_id=None,
                     requester_id=None,
                     **kwargs):
        if side == 'buy':
            response = self.rest_client.buy_limit(
                BittrexService._to_market(base, quote), quantity, price)
        elif side == 'sell':
            response = self.rest_client.sell_limit(
                BittrexService._to_market(base, quote), quantity, price)
        else:
            raise NotImplementedError('Side of {} is unknown for {}', side,
                                      self.name)

        quantity = str(quantity)
        price = str(price)

        if response is None:
            internal_response = {
                'action': 'CREATE_FAILED',
                'reason': 'UNKNOWN',
                'exchange': self.name,
                'base': base,
                'quote': quote,
                'internal_order_id': internal_order_id,
                'side': side,
                'quantity': quantity,
                'price': price,
                'cum_quantity_filled': 0,
                'received_ms': time() * 1000
            }

        elif 'success' in response and response['success'] is False:
            reason = 'UNKNOWN'
            if response['message'] == 'INSUFFICIENT_FUNDS':
                reason = response['message']
            internal_response = {
                'action': 'CREATE_FAILED',
                'reason': reason,
                'exchange': self.name,
                'base': base,
                'quote': quote,
                'internal_order_id': internal_order_id,
                'side': side,
                'quantity': quantity,
                'price': price,
                'cum_quantity_filled': 0,
                'received_ms': time() * 1000
            }
        else:
            exchange_id = response['result']['uuid']
            internal_response = {
                'action': 'CREATED',
                'exchange': self.name,
                'base': base,
                'quote': quote,
                'exchange_order_id': exchange_id,
                'internal_order_id': internal_order_id,
                'side': side,
                'quantity': quantity,
                'price': price,
                'cum_quantity_filled': 0,
                'order_status': 'OPEN',
                'server_ms': time() * 1000,
                'received_ms': time() * 1000
            }

            open_order = internal_response.copy()
            open_order['price'] = Decimal(open_order['price'])
            open_order['quantity'] = Decimal(open_order['quantity'])
            self.open_orders.append(internal_response)

        self.notify_callbacks('trade_lifecycle', data=internal_response)

        return internal_response

    def cancel_order(self,
                     base,
                     quote,
                     internal_order_id,
                     request_id,
                     requester_id=None,
                     exchange_order_id=None):
        index_to_pop = None
        if exchange_order_id is None:
            i = 0
            for open_order in self.open_orders:
                if open_order['internal_order_id'] == internal_order_id:
                    exchange_order_id = open_order['exchange_order_id']
                    index_to_pop = i
                    break
                i += 1

        response = self.rest_client.cancel(exchange_order_id)

        if response['success'] is True:
            i = 0

            if index_to_pop is None:
                for order in self.open_orders:
                    if order['exchange_order_id'] == exchange_order_id:
                        index_to_pop = i
                        break
                    i += 1

            if index_to_pop is not None:
                self.open_orders.pop(index_to_pop)

            self.notify_callbacks('trade_lifecycle',
                                  data={
                                      'action': 'CANCELED',
                                      'base': base,
                                      'quote': quote,
                                      'exchange': self.name,
                                      'exchange_order_id': exchange_order_id,
                                      'internal_order_id': internal_order_id,
                                      'order_status': 'CANCELED',
                                      'server_ms': int(round(time() * 1000)),
                                      'received_ms': int(round(time() * 1000))
                                  })
        else:
            reason = response['message']
            if response['message'] == 'INVALID_ORDER' or\
               response['message'] == 'ORDER_NOT_OPEN' or\
               response['message'] == 'UUID_INVALID':
                reason = 'order_not_found'

            self.notify_callbacks('trade_lifecycle',
                                  data={
                                      'action': 'CANCEL_FAILED',
                                      'base': base,
                                      'quote': quote,
                                      'reason': reason,
                                      'exchange': self.name,
                                      'exchange_order_id': exchange_order_id,
                                      'internal_order_id': internal_order_id,
                                      'order_status': 'UNKNOWN',
                                      'server_ms': int(round(time() * 1000)),
                                      'received_ms': int(round(time() * 1000))
                                  })

    def cancel_all(self, base, quote):
        open_orders_resp = self.rest_client.get_open_orders(
            BittrexService._to_market(base, quote))
        open_orders = open_orders_resp['result']
        for open_order in open_orders:

            exchange_order_id = open_order['OrderUuid']
            internal_order_id = None

            for order in self.open_orders:
                if order['exchange_order_id'] == exchange_order_id:
                    internal_order_id = order['internal_order_id']
                    break

            self.cancel_order(base,
                              quote,
                              internal_order_id,
                              'a_request_id',
                              exchange_order_id=exchange_order_id)

    def can_withdraw(self, currency):
        return True

    def withdraw(self, currency, amount, address, tag=None, cb=None, **kwargs):
        # TODO - Internal format and cb
        self.rest_client.withdraw(currency, address, amount)

    def can_deposit(self, currency):
        return True

    def get_deposit_address(self, currency):
        response = self.rest_client.get_deposit_address(currency)
        return response['result']['Address']

    def get_deposits(self, currency=None):
        # TODO - Internal format
        return self.rest_client.get_deposit_history(currency)

    def get_withdrawals(self, currency):
        # TODO - Internal format
        return self.rest_client.get_withdrawal_history(currency)

    def get_order_by_exchange_id(self, exchange_id):
        for open_order in self.open_orders.copy():
            if open_order['exchange_order_id'] == exchange_id:
                return open_order

        return None

    def get_public_trades(self, base, quote, start_s, end_s):
        pass

    def get_our_trades(self, base, quote, start_s, end_s):
        pass
Esempio n. 15
0
File: cpm.py Progetto: altfund/cpm
                    bitfinex_instance.place_order(amount=trade_size,
                                                  price=None,
                                                  side="buy",
                                                  ord_type="market",
                                                  symbol=pairname)
            if exchange == "BITTREX":
                print("Acquiring " + str(trade_size) + " " + currency +
                      " on " + exchange)
                if not test:
                    pairname = transfer_currency + "-" + currency
                    ## market orders are disabled for bittrex, we will use a limit order to cross the spread
                    buy_price = float(
                        bittrex_instance.get_ticker(
                            market=pairname)['result']['Ask'])
                    bittrex_instance.buy_limit(market=pairname,
                                               quantity=trade_size,
                                               rate=buy_price)
                # make market order at trade_size, base transfer_currency
                # save the orders to csv

#As the transfer & one investment coin is the same, we do not buy 10% ETH, we buy 60% ETH and than send it as above described to Bitfinex and Bittrex.

#As soon as the ETH arrives there the buy actions above will be made.
## the script will account for the optimal/actual balances each time it is run, triggering will have to come from elsewhere

#Time of every transaction including it's fees and prices must be stored into the database. The price should be stored in both the base currency and the actual used coin (note - e.g. IOTA must be bought from EUR->ETH->IOTA) so I need the price EUR/IOTA & ETH/IOTA.
## we have no way to track transactions since they have to be cleared on the exchange before we can get any info about them
## so the prices/stats that you want will have to be collected and attributed after-the-fact since they are not returned at the time of orders
## for now we are using market orders, but would recommend switching to limit orders for safety asap

#Please also provide a ready to use installation how to get this installed on a local docker.