示例#1
0
    def get_ticker(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        return self._get('/v1/future_ticker.do?symbol={}&contract_type=quarter'
                         ''.format(symbol_pair),
                         model_class=OkexTicker)
示例#2
0
    def get_ticker(self, symbol_pair, **kwargs):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        return self._get('/v1/pubticker/{}'.format(symbol_pair),
                         model_class=BitfinexTicker,
                         **kwargs)
示例#3
0
    def get_order_book(self, symbol_pair, **kwargs):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        return self._get('/v1/book/{}'.format(symbol_pair),
                         model_class=BitfinexOrderBook,
                         **kwargs)
示例#4
0
    def get_order_book(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        params = {'pair': symbol_pair}
        return self._get('/0/public/Depth',
                         params=params,
                         model_class=KrakenOrderBook)
示例#5
0
    def get_ticker(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        params = {'pair': symbol_pair}
        return self._get('/0/public/Ticker',
                         params=params,
                         transformation=self._transform_ticker,
                         model_class=KrakenTicker)
示例#6
0
    def get_open_orders(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        path = '/v1/orders'
        payload = {'request': path, 'nonce': str(time.time())}
        signed_payload = self._sign_payload(payload)
        data = self._post(path,
                          headers=signed_payload,
                          model_class=BitfinexOrder)
        return [order for order in data if order['symbol_pair'] == symbol_pair]
示例#7
0
def volume_weighted_average_price(action, order_book, amount):
    """
    Calculates the weighted average price of an operation (sell/buy)
    for a given `amount` and `order_book`.

    @params:
        * action: exchanges.ACTIONS choice
        * order_book: models.base.OrderBook instance or subclass
        * amount: Decimal or valid numeric argument representing volume to operate.

    @returns:
        a Decimal object representing the weighted average price.
    """
    # validate arguments
    is_restricted_to_values(action, exchanges.ACTIONS)

    is_instance(amount, (Decimal, float, int, str))
    passes_test(amount, lambda x: Decimal(x))

    order_list = order_book.asks if action == exchanges.BUY else order_book.bids

    total_market_depth = sum([t[1] for t in order_list])
    if amount > total_market_depth:
        raise exceptions.InsufficientMarketDepth(
            'Not enough depth in OrderBook to {} {} volume'.format(
                action, amount))

    if action == exchanges.BUY:
        # when checking the "asks" list, we want to
        # iterate orders from cheapest to highest
        order_list = list(reversed(order_list))
    accum = Decimal(0.0)

    # most of the times last used order in the orderbook
    # is partially used. we need to know which was the portion
    # used from that order to calculate the weighted average
    rest = amount

    for index, price_tuple in enumerate(order_list):
        volume = price_tuple[1]
        accum += volume
        if accum >= amount:
            break
        rest -= volume

    # get the sub list representing only the necessary
    # orders to fulfill the amount amount
    sub_list = order_list[:index + 1]

    # change the last used order in the list, to just
    # the needed rest amount
    sub_list[-1] = (sub_list[-1][0], Decimal(rest))

    sub_list_amounts = [t[1] for t in sub_list]
    return sum(x * y for x, y in sub_list) / sum(sub_list_amounts)
示例#8
0
    def get_order_book(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        OkexOrderBook.TICKER = getattr(self, '{}_ticker'.format(symbol_pair))
        OkexOrderBook.SYMBOL = symbol_pair
        OkexOrderBook.CONTRACT_UNIT_AMOUNTS = self.CONTRACT_UNIT_AMOUNTS
        return self._get(
            '/v1/future_depth.do?size=100&symbol={}&contract_type=quarter'
            ''.format(symbol_pair),
            model_class=OkexOrderBook)
示例#9
0
    def get_open_positions(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        path = '/v1/positions'
        payload = {
            'request': path,
            'nonce': str(time.time()),
        }
        signed_payload = self._sign_payload(payload)
        positions = self._post(path,
                               headers=signed_payload,
                               model_class=BitfinexPosition)
        return [pos for pos in positions if pos['symbol_pair'] == symbol_pair]
示例#10
0
    def cancel_all_orders(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        path = '/0/private/CancelOrder'
        payload = {
            'nonce': int(1000 * time.time()),
            'txid': self.get_userref(symbol_pair)
        }
        headers = {
            'API-Key': self.api_key,
            'API-Sign': self._sign_payload(path, payload)
        }
        return self._post(path, headers=headers, body=payload)
示例#11
0
    def cancel_all_orders(self, symbol_pair, **kwargs):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        path = '/v1/order/cancel/multi'
        orders = self.get_open_orders(symbol_pair=symbol_pair)
        if not orders:
            return
        payload = {
            'request': path,
            'nonce': str(time.time()),
            'order_ids': [order.id for order in orders]
        }
        signed_payload = self._sign_payload(payload)
        return self._post(path, headers=signed_payload, **kwargs)
示例#12
0
    def close_all_positions(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        positions = self.get_open_positions(symbol_pair=symbol_pair)
        for pos in positions:
            # as we want to close the position,
            # we need to performe the opposite action to the given one.
            action = exchanges.SELL if pos.action == exchanges.BUY else exchanges.BUY
            self.open_order(action,
                            pos.amount,
                            pos.symbol_pair,
                            pos.price,
                            exchanges.MARKET,
                            amount_in_contracts=True,
                            closing=True)
示例#13
0
    def get_open_positions(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        path = '/v1/future_position.do'
        params = {
            'symbol': symbol_pair,
            'contract_type': 'quarter',
        }
        params['api_key'] = self.api_key
        params['sign'] = self._sign_params(params)
        return self._post(path,
                          params=params,
                          transformation=self._transform_open_positions,
                          model_class=OkexPosition)
示例#14
0
    def get_account_balance(self, symbol=None):
        is_restricted_to_values(symbol, currencies.SYMBOLS + [None])

        path = '/v1/balances'
        payload = {'request': path, 'nonce': str(time.time())}
        signed_payload = self._sign_payload(payload)
        data = self._post(path,
                          headers=signed_payload,
                          transformation=self._transform_account_balance,
                          model_class=BitfinexAccountBalance)
        if symbol is None:
            return data
        for symbol_balance in data:
            if symbol_balance.symbol == symbol:
                return symbol_balance
        return self._empty_account_balance(symbol)
示例#15
0
    def close_position(self, position_id, symbol_pair, **kwargs):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        positions = self.get_open_positions(symbol_pair)
        try:
            pos = [pos for pos in positions if pos.id == position_id][0]
        except IndexError:
            raise self.ERROR_CLASS('Could not find position with '
                                   'ID: "{}"'.format(position_id))

        # as we want to close the position,
        # we need to performe the opposite action to the given one.
        action = exchanges.SELL if pos.action == exchanges.BUY else exchanges.BUY

        return self.open_order(action, pos.amount, pos.symbol_pair, pos.price,
                               exchanges.MARKET, **kwargs)
示例#16
0
    def get_open_orders(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        path = '/0/private/OpenOrders'
        payload = {
            'nonce': int(1000 * time.time()),
        }
        headers = {
            'API-Key': self.api_key,
            'API-Sign': self._sign_payload(path, payload)
        }
        data = self._post(path,
                          headers=headers,
                          body=payload,
                          transformation=self._transform_open_orders,
                          model_class=KrakenOrder)
        return [order for order in data if order['symbol_pair'] == symbol_pair]
示例#17
0
    def cancel_all_orders(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        orders = self.get_open_orders(symbol_pair=symbol_pair)
        if not orders:
            return

        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        order_ids = ','.join([order.id for order in orders])
        path = '/v1/future_cancel.do'
        params = {
            'symbol': symbol_pair,
            'contract_type': 'quarter',
            'order_id': order_ids,
        }
        params['api_key'] = self.api_key
        params['sign'] = self._sign_params(params)
        return self._post(path, params=params)
示例#18
0
    def get_account_balance(self, symbol=None):
        is_restricted_to_values(symbol, currencies.SYMBOLS + [None])

        path = '/v1/future_userinfo.do'
        params = {}
        params['api_key'] = self.api_key
        params['sign'] = self._sign_params(params)
        data = self._post(path,
                          params=params,
                          transformation=self._transform_account_balance,
                          model_class=OkexAccountBalance)
        if symbol is None:
            return data
        for symbol_balance in data:
            if symbol_balance.symbol == symbol:
                return symbol_balance
        raise self.ERROR_CLASS(
            'Symbol "{}" was not found in the account balance'.format(symbol))
示例#19
0
    def get_open_positions(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        path = '/0/private/OpenPositions'
        payload = {
            'nonce': int(1000 * time.time()),
            'docalcs': True,
        }
        headers = {
            'API-Key': self.api_key,
            'API-Sign': self._sign_payload(path, payload)
        }
        positions = self._post(path,
                               headers=headers,
                               body=payload,
                               transformation=self._transform_open_positions,
                               model_class=KrakenPosition)
        return [pos for pos in positions if pos['symbol_pair'] == symbol_pair]
示例#20
0
    def get_open_orders(self, symbol_pair):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        path = '/v1/future_order_info.do'
        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        params = {
            'symbol': symbol_pair,
            'contract_type': 'quarter',
            'status': self.ORDER_STATUS['unfilled'],
            'order_id': -1,  # all orders with given "status"
            'current_page': 1,
            'page_length': 50,
        }
        params['api_key'] = self.api_key
        params['sign'] = self._sign_params(params)
        data = self._post(path,
                          params=params,
                          transformation=self._transform_open_orders,
                          model_class=OkexOrder)
        return [order for order in data if order['symbol_pair'] == symbol_pair]
示例#21
0
def worst_order_price(action, order_book, amount):
    """
    Calculates the worst used order price in given `order_book` to fulfill
    an operation (sell/buy) of the given `amount`.

    @params:
        * action: exchanges.ACTIONS choice
        * order_book: models.base.OrderBook instance or subclass
        * amount: Decimal or valid numeric argument representing volume to operate.

    @returns:
        a Decimal object representing the worst order price.
    """
    # validate arguments
    is_restricted_to_values(action, exchanges.ACTIONS)

    is_instance(amount, (Decimal, float, int, str))
    passes_test(amount, lambda x: Decimal(x))

    order_list = order_book.asks if action == exchanges.BUY else order_book.bids

    total_market_depth = sum([t[1] for t in order_list])
    if amount > total_market_depth:
        raise exceptions.InsufficientMarketDepth(
            'Not enough depth in OrderBook to {} {} volume'.format(
                action, amount))

    if action == exchanges.BUY:
        # when checking the "asks" list, we want to
        # iterate orders from cheapest to highest
        order_list = list(reversed(order_list))

    accum = Decimal('0')
    for price_tuple in order_list:
        price, volume = price_tuple
        accum += volume
        if accum >= amount:
            return price
示例#22
0
    def get_account_balance(self, symbol=None):
        is_restricted_to_values(symbol, currencies.SYMBOLS + [None])

        path = '/0/private/Balance'
        payload = {
            'nonce': int(1000 * time.time()),
        }
        headers = {
            'API-Key': self.api_key,
            'API-Sign': self._sign_payload(path, payload)
        }
        data = self._post(path,
                          headers=headers,
                          body=payload,
                          transformation=self._transform_account_balance,
                          model_class=KrakenAccountBalance)

        if symbol is None:
            return data
        for symbol_balance in data:
            if symbol_balance.symbol == symbol:
                return symbol_balance
        return self._empty_account_balance(symbol)
示例#23
0
    def open_order(self, action, amount, symbol_pair, price, order_type):
        """
        Creates a new Order.

        :action:
            exchanges.ACTIONS choice
        :amount:
            Decimal, float, integer or string representing number value.
        :symbol_pair:
            currencies.SYMBOL_PAIRS choice
        :price:
            Decimal, float, integer or string representing number value.
        :order_type:
            exchanges.ORDER_TYPES choice
        """
        # validate arguments
        is_restricted_to_values(action, exchanges.ACTIONS)

        is_instance(amount, (Decimal, float, int, str))
        passes_test(amount, lambda x: Decimal(x))

        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        is_instance(price, (Decimal, float, int, str))
        passes_test(price, lambda x: isinstance(Decimal(x), Decimal))

        is_restricted_to_values(order_type, exchanges.ORDER_TYPES)

        path = '/0/private/AddOrder'
        userref = self.get_userref(symbol_pair)
        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        payload = {
            'pair': symbol_pair,
            'type': action,
            'ordertype': order_type,
            'price': Decimal(str(price)),
            'volume': Decimal(str(amount)),
            'leverage': 2,
            'nonce': int(1000 * time.time()),
            'userref': userref,
        }
        headers = {
            'API-Key': self.api_key,
            'API-Sign': self._sign_payload(path, payload)
        }
        return self._post(path,
                          headers=headers,
                          body=payload,
                          transformation=self._transform_new_order,
                          model_class=KrakenOrder)
示例#24
0
    def open_order(self, action, amount, symbol_pair, price, order_type,
                   **kwargs):
        """
        Creates a new Order.

        :action:
            exchanges.ACTIONS choice
        :amount:
            Decimal, float, integer or string representing number value.
        :symbol_pair:
            currencies.SYMBOL_PAIRS choice
        :price:
            Decimal, float, integer or string representing number value.
        :order_type:
            exchanges.ORDER_TYPES choice
        """
        # validate arguments
        is_restricted_to_values(action, exchanges.ACTIONS)

        is_instance(amount, (Decimal, float, int, str))
        passes_test(amount, lambda x: Decimal(x))

        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        is_instance(price, (Decimal, float, int, str))
        passes_test(price, lambda x: isinstance(Decimal(x), Decimal))

        is_restricted_to_values(order_type, exchanges.ORDER_TYPES)

        path = '/v1/order/new'
        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        payload = {
            'request': path,
            'nonce': str(time.time()),
            'side': action,
            'amount': str(amount),
            'symbol': symbol_pair,
            'price': str(price),
            'type': order_type,
        }
        signed_payload = self._sign_payload(payload)
        return self._post(path,
                          headers=signed_payload,
                          model_class=BitfinexOrder,
                          **kwargs)
示例#25
0
    def open_order(self,
                   action,
                   amount,
                   symbol_pair,
                   price,
                   order_type,
                   amount_in_contracts=False,
                   closing=False):
        """
        Creates a new Order.

        :action:
            exchanges.ACTIONS choice
        :amount:
            Decimal, float, integer or string representing number value.
            If `amount_in_contracts == True`, `amount` needs to be an
            integer number greater or equal to 1.
        :symbol_pair:
            currencies.SYMBOL_PAIRS choice
        :price:
            Decimal, float, integer or string representing number value.
        :order_type:
            exchanges.ORDER_TYPES choice
        :amount_in_contracts:
            (True|False) Whether the `amount`  argument is expressed in cryptos or contracts
        :closing:
            (True|False) Whether the order we are opening is to close an existing position or not
        """
        # validate arguments
        is_restricted_to_values(action, exchanges.ACTIONS)

        is_instance(amount, (Decimal, float, int, str))
        passes_test(amount, lambda x: Decimal(x))
        if amount_in_contracts:
            passes_test(amount, lambda x: Decimal(x) >= 1)

        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        is_instance(price, (Decimal, float, int, str))
        passes_test(price, lambda x: Decimal(x))

        is_restricted_to_values(order_type, exchanges.ORDER_TYPES)

        is_instance(amount_in_contracts, bool)
        is_instance(closing, bool)

        path = '/v1/future_trade.do'
        symbol_pair = self.SYMBOLS_MAPPING[symbol_pair]
        if closing:
            action = (self.ACTION['close_long'] if action == exchanges.SELL
                      else self.ACTION['close_short'])
        else:
            action = (self.ACTION['open_short'] if action == exchanges.SELL
                      else self.ACTION['open_long'])

        if not amount_in_contracts:
            amount = crypto_to_contracts(
                amount,
                getattr(self, '{}_ticker'.format(symbol_pair)).last,
                self.CONTRACT_UNIT_AMOUNTS[symbol_pair])

        match_price = 1 if order_type == 'market' else 0
        params = {
            'symbol': symbol_pair,
            'contract_type': 'quarter',
            'price': float(Decimal(price)),
            'match_price': match_price,  # if market, 'price' field is ignored
            'amount': int(amount),  # in contracts
            'type': action,
            'lever_rate': 10,  # default
        }
        params['api_key'] = self.api_key
        params['sign'] = self._sign_params(params)
        return self._post(path, params=params, model_class=OkexOrder)
示例#26
0
    def close_all_positions(self, symbol_pair, **kwargs):
        is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS)

        positions = self.get_open_positions(symbol_pair=symbol_pair)
        for pos in positions:
            self.close_position(pos.id, pos.symbol_pair, **kwargs)