Example #1
0
    def create_order(self, asset, amount, is_buy, style):
        """
        Creating order on the exchange.

        :param asset:
        :param amount:
        :param is_buy:
        :param style:
        :return:
        """
        exchange_symbol = self.get_symbol(asset)
        if isinstance(style, ExchangeLimitOrder) \
                or isinstance(style, ExchangeStopLimitOrder):
            price = style.get_limit_price(is_buy)
            order_type = 'limit'

        elif isinstance(style, ExchangeStopOrder):
            price = style.get_stop_price(is_buy)
            order_type = 'stop'

        else:
            raise InvalidOrderStyle(exchange=self.name,
                                    style=style.__class__.__name__)

        req = dict(
            symbol=exchange_symbol,
            amount=str(float(abs(amount))),
            price="{:.20f}".format(float(price)),
            side='buy' if is_buy else 'sell',
            type='exchange ' + order_type,  # TODO: support margin trades
            exchange=self.name,
            is_hidden=False,
            is_postonly=False,
            use_all_available=0,
            ocoorder=False,
            buy_price_oco=0,
            sell_price_oco=0)

        date = pd.Timestamp.utcnow()
        try:
            self.ask_request()
            response = self._request('order/new', req)
            order_status = response.json()
        except Exception as e:
            raise ExchangeRequestError(error=e)

        if 'message' in order_status:
            raise ExchangeRequestError(
                error='unable to create Bitfinex order {}'.format(
                    order_status['message']))

        order_id = str(order_status['id'])
        order = Order(dt=date,
                      asset=asset,
                      amount=amount,
                      stop=style.get_stop_price(is_buy),
                      limit=style.get_limit_price(is_buy),
                      id=order_id)

        return order
Example #2
0
    def create_order(self, asset, amount, is_buy, style):
        log.info('creating {} order'.format('buy' if is_buy else 'sell'))
        exchange_symbol = self.get_symbol(asset)

        if isinstance(style, LimitOrder) or isinstance(style, StopLimitOrder):
            if isinstance(style, StopLimitOrder):
                log.warn('{} will ignore the stop price'.format(self.name))

            price = style.get_limit_price(is_buy)
            try:
                if is_buy:
                    order_status = self.api.buylimit(exchange_symbol, amount,
                                                     price)
                else:
                    order_status = self.api.selllimit(exchange_symbol,
                                                      abs(amount), price)
            except Exception as e:
                raise ExchangeRequestError(error=e)

            if 'uuid' in order_status:
                order_id = order_status['uuid']
                order = Order(dt=pd.Timestamp.utcnow(),
                              asset=asset,
                              amount=amount,
                              stop=style.get_stop_price(is_buy),
                              limit=style.get_limit_price(is_buy),
                              id=order_id)
                return order
            else:
                raise CreateOrderError(exchange=self.name, error=order_status)
        else:
            raise InvalidOrderStyle(exchange=self.name,
                                    style=style.__class__.__name__)
Example #3
0
    def create_order(self, asset, amount, is_buy, style):
        symbol = self.get_symbol(asset)

        if isinstance(style, ExchangeLimitOrder):
            price = style.get_limit_price(is_buy)
            order_type = 'limit'

        elif isinstance(style, MarketOrder):
            price = None
            order_type = 'market'

        else:
            raise InvalidOrderStyle(exchange=self.name,
                                    style=style.__class__.__name__)

        side = 'buy' if amount > 0 else 'sell'

        if hasattr(self.api, 'amount_to_lots'):
            adj_amount = self.api.amount_to_lots(
                symbol=symbol,
                amount=abs(amount),
            )
            if adj_amount != abs(amount):
                log.info(
                    'adjusted order amount {} to {} based on lot size'.format(
                        abs(amount),
                        adj_amount,
                    ))
        else:
            adj_amount = abs(amount)

        try:
            result = self.api.create_order(symbol=symbol,
                                           type=order_type,
                                           side=side,
                                           amount=adj_amount,
                                           price=price)
        except ExchangeNotAvailable as e:
            log.debug('unable to create order: {}'.format(e))
            raise ExchangeRequestError(error=e)

        except InvalidOrder as e:
            log.warn('the exchange rejected the order: {}'.format(e))
            raise CreateOrderError(exchange=self.name, error=e)

        if 'info' not in result:
            raise ValueError('cannot use order without info attribute')

        final_amount = adj_amount if side == 'buy' else -adj_amount
        order_id = result['id']
        order = Order(dt=pd.Timestamp.utcnow(),
                      asset=asset,
                      amount=final_amount,
                      stop=style.get_stop_price(is_buy),
                      limit=style.get_limit_price(is_buy),
                      id=order_id)
        return order
Example #4
0
    def create_order(self, asset, amount, is_buy, style):
        """
        Creating order on the exchange.

        :param asset:
        :param amount:
        :param is_buy:
        :param style:
        :return:
        """
        exchange_symbol = self.get_symbol(asset)

        if isinstance(style, ExchangeLimitOrder) or isinstance(style,
                                                               ExchangeStopLimitOrder):
            if isinstance(style, ExchangeStopLimitOrder):
                log.warn('{} will ignore the stop price'.format(self.name))

            price = style.get_limit_price(is_buy)

            try:
                if (is_buy):
                    response = self.api.buy(exchange_symbol, amount, price)
                else:
                    response = self.api.sell(exchange_symbol, -amount, price)
            except Exception as e:
                raise ExchangeRequestError(error=e)

            date = pd.Timestamp.utcnow()

            if ('orderNumber' in response):
                order_id = str(response['orderNumber'])
                order = Order(
                    dt=date,
                    asset=asset,
                    amount=amount,
                    stop=style.get_stop_price(is_buy),
                    limit=style.get_limit_price(is_buy),
                    id=order_id
                )
                return order
            else:
                log.warn(
                    '{} order failed: {}'.format('buy' if is_buy else 'sell',
                                                 response['error']))
                return None
        else:
            raise InvalidOrderStyle(exchange=self.name,
                                    style=style.__class__.__name__)
Example #5
0
    def create_order(self, asset, amount, is_buy, style):
        log.info('creating {} order'.format('buy' if is_buy else 'sell'))
        exchange_symbol = self.get_symbol(asset)

        if isinstance(style, LimitOrder) or isinstance(style, StopLimitOrder):
            if isinstance(style, StopLimitOrder):
                log.warn('{} will ignore the stop price'.format(self.name))

            price = style.get_limit_price(is_buy)
            try:
                self.ask_request()
                if is_buy:
                    order_status = self.api.buylimit(exchange_symbol, amount,
                                                     price)
                else:
                    order_status = self.api.selllimit(exchange_symbol,
                                                      abs(amount), price)
            except Exception as e:
                raise ExchangeRequestError(error=e)

            if 'uuid' in order_status:
                order_id = order_status['uuid']
                order = Order(dt=pd.Timestamp.utcnow(),
                              asset=asset,
                              amount=amount,
                              stop=style.get_stop_price(is_buy),
                              limit=style.get_limit_price(is_buy),
                              id=order_id)
                return order
            else:
                if order_status == 'INSUFFICIENT_FUNDS':
                    log.warn('not enough funds to create order')
                    return None
                elif order_status == 'DUST_TRADE_DISALLOWED_MIN_VALUE_50K_SAT':
                    log.warn('Your order is too small, order at least 50K'
                             ' Satoshi')
                    return None
                else:
                    raise CreateOrderError(exchange=self.name,
                                           error=order_status)
        else:
            raise InvalidOrderStyle(exchange=self.name,
                                    style=style.__class__.__name__)
Example #6
0
    def order(self,
              asset,
              amount,
              limit_price=None,
              stop_price=None,
              style=None):
        """Place an order.

        Parameters
        ----------
        asset : Asset
            The asset that this order is for.
        amount : int
            The amount of shares to order. If ``amount`` is positive, this is
            the number of shares to buy or cover. If ``amount`` is negative,
            this is the number of shares to sell or short.
        limit_price : float, optional
            The limit price for the order.
        stop_price : float, optional
            The stop price for the order.
        style : ExecutionStyle, optional
            The execution style for the order.

        Returns
        -------
        order_id : str or None
            The unique identifier for this order, or None if no order was
            placed.

        Notes
        -----
        The ``limit_price`` and ``stop_price`` arguments provide shorthands for
        passing common execution styles. Passing ``limit_price=N`` is
        equivalent to ``style=LimitOrder(N)``. Similarly, passing
        ``stop_price=M`` is equivalent to ``style=StopOrder(M)``, and passing
        ``limit_price=N`` and ``stop_price=M`` is equivalent to
        ``style=StopLimitOrder(N, M)``. It is an error to pass both a ``style``
        and ``limit_price`` or ``stop_price``.

        See Also
        --------
        :class:`catalyst.finance.execution.ExecutionStyle`
        :func:`catalyst.api.order_value`
        :func:`catalyst.api.order_percent`
        """
        if amount == 0:
            log.warn('skipping order amount of 0')
            return None

        if asset.base_currency != self.base_currency.lower():
            raise MismatchingBaseCurrencies(base_currency=asset.base_currency,
                                            algo_currency=self.base_currency)

        is_buy = (amount > 0)

        if limit_price is not None and stop_price is not None:
            style = ExchangeStopLimitOrder(limit_price,
                                           stop_price,
                                           exchange=self.name)
        elif limit_price is not None:
            style = ExchangeLimitOrder(limit_price, exchange=self.name)

        elif stop_price is not None:
            style = ExchangeStopOrder(stop_price, exchange=self.name)

        elif style is not None:
            raise InvalidOrderStyle(exchange=self.name.title(),
                                    style=style.__class__.__name__)
        else:
            raise ValueError('Incomplete order data.')

        display_price = limit_price if limit_price is not None else stop_price
        log.debug(
            'issuing {side} order of {amount} {symbol} for {type}: {price}'.
            format(side='buy' if is_buy else 'sell',
                   amount=amount,
                   symbol=asset.symbol,
                   type=style.__class__.__name__,
                   price='{}{}'.format(display_price, asset.base_currency)))
        order = self.create_order(asset, amount, is_buy, style)
        if order:
            self._portfolio.create_order(order)
            return order.id
        else:
            return None
Example #7
0
    def create_order(self, asset, amount, is_buy, style):
        symbol = self.get_symbol(asset)

        if isinstance(style, ExchangeLimitOrder):
            price = style.get_limit_price(is_buy)
            order_type = 'limit'

        elif isinstance(style, MarketOrder):
            price = None
            order_type = 'market'

        else:
            raise InvalidOrderStyle(exchange=self.name,
                                    style=style.__class__.__name__)

        side = 'buy' if amount > 0 else 'sell'
        if hasattr(self.api, 'amount_to_lots'):
            # TODO: is this right?
            if self.api.markets is None:
                self.api.load_markets()

            # https://github.com/ccxt/ccxt/issues/1483
            adj_amount = round(abs(amount), asset.decimals)
            market = self.api.markets[symbol]
            if 'lots' in market and market['lots'] > amount:
                raise CreateOrderError(
                    exchange=self.name,
                    e='order amount lower than the smallest lot: {}'.format(
                        amount))

        else:
            adj_amount = round(abs(amount), asset.decimals)

        before_order_dt = pd.Timestamp.utcnow()
        try:
            result = self.api.create_order(symbol=symbol,
                                           type=order_type,
                                           side=side,
                                           amount=adj_amount,
                                           price=price)
        except InvalidOrder as e:
            log.warn('the exchange rejected the order: {}'.format(e))
            raise CreateOrderError(exchange=self.name, error=e)

        except RequestTimeout as e:
            log.info('received a RequestTimeout exception while creating '
                     'an order on {} / {}\n Checking if an order was filled '
                     'during the timeout'.format(self.name, symbol))

            missing_order = self._handle_request_timeout(
                before_order_dt, asset, amount, is_buy, style, adj_amount)
            if missing_order is None:
                # no order was found
                log.warn(
                    'no order was identified during timeout exception.'
                    'Please double check for inconsistency with the exchange. '
                    'We encourage you to report any issue on GitHub: '
                    'https://github.com/enigmampc/catalyst/issues')
                raise ExchangeRequestError(error=e)
            else:
                return missing_order

        except (ExchangeError, NetworkError) as e:
            log.warn('unable to create order {} / {}: {}'.format(
                self.name, symbol, e))
            raise ExchangeRequestError(error=e)

        exchange_amount = None
        if 'amount' in result and result['amount'] != adj_amount:
            exchange_amount = result['amount']

        elif 'info' in result:
            if 'origQty' in result['info']:
                exchange_amount = float(result['info']['origQty'])

        if exchange_amount:
            log.info('order amount adjusted by {} from {} to {}'.format(
                self.name, adj_amount, exchange_amount))
            adj_amount = exchange_amount

        if 'info' not in result:
            raise ValueError('cannot use order without info attribute')

        final_amount = adj_amount if side == 'buy' else -adj_amount
        order_id = result['id']
        order = Order(dt=pd.Timestamp.utcnow(),
                      asset=asset,
                      amount=final_amount,
                      stop=style.get_stop_price(is_buy),
                      limit=style.get_limit_price(is_buy),
                      id=order_id)
        return order
Example #8
0
    def create_order(self, asset, amount, is_buy, style):
        symbol = self.get_symbol(asset)

        if isinstance(style, ExchangeLimitOrder):
            price = style.get_limit_price(is_buy)
            order_type = 'limit'

        elif isinstance(style, MarketOrder):
            price = None
            order_type = 'market'

        else:
            raise InvalidOrderStyle(exchange=self.name,
                                    style=style.__class__.__name__)

        side = 'buy' if amount > 0 else 'sell'
        if hasattr(self.api, 'amount_to_lots'):
            # TODO: is this right?
            if self.api.markets is None:
                self.api.load_markets()

            # https://github.com/ccxt/ccxt/issues/1483
            adj_amount = round(abs(amount), asset.decimals)
            market = self.api.markets[symbol]
            if 'lots' in market and market['lots'] > amount:
                raise CreateOrderError(
                    exchange=self.name,
                    e='order amount lower than the smallest lot: {}'.format(
                        amount))

        else:
            adj_amount = round(abs(amount), asset.decimals)

        try:
            result = self.api.create_order(symbol=symbol,
                                           type=order_type,
                                           side=side,
                                           amount=adj_amount,
                                           price=price)
        except InvalidOrder as e:
            log.warn('the exchange rejected the order: {}'.format(e))
            raise CreateOrderError(exchange=self.name, error=e)

        except (ExchangeError, NetworkError) as e:
            log.warn('unable to create order {} / {}: {}'.format(
                self.name, symbol, e))
            raise ExchangeRequestError(error=e)

        exchange_amount = None
        if 'amount' in result and result['amount'] != adj_amount:
            exchange_amount = result['amount']

        elif 'info' in result:
            if 'origQty' in result['info']:
                exchange_amount = float(result['info']['origQty'])

        if exchange_amount:
            log.info('order amount adjusted by {} from {} to {}'.format(
                self.name, adj_amount, exchange_amount))
            adj_amount = exchange_amount

        if 'info' not in result:
            raise ValueError('cannot use order without info attribute')

        final_amount = adj_amount if side == 'buy' else -adj_amount
        order_id = result['id']
        order = Order(dt=pd.Timestamp.utcnow(),
                      asset=asset,
                      amount=final_amount,
                      stop=style.get_stop_price(is_buy),
                      limit=style.get_limit_price(is_buy),
                      id=order_id)
        return order