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
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__)
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
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__)
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__)
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
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
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