Exemple #1
0
 def __getattr__(self, attr):
     exch = self.lookup[attr.lower()]
     if not exch.mapped:
         try:
             load_exchange_symbol_mapping(exch.ID + 'REST')
         except KeyError:
             load_exchange_symbol_mapping(exch.ID)
         exch.mapped = True
     return exch
Exemple #2
0
 def __getitem__(self, key):
     if not self.mapped:
         try:
             load_exchange_symbol_mapping(self.ID + 'REST')
         except KeyError:
             load_exchange_symbol_mapping(self.ID)
         self.mapped = True
     if key == 'trades':
         return self.trades
     elif key == 'funding':
         return self.funding
     elif key == 'l2_book':
         return self.l2_book
     elif key == 'l3_book':
         return self.l3_book
     elif key == 'ticker':
         return self.ticker
Exemple #3
0
    def __init__(self,
                 address: Union[dict, str],
                 sandbox=False,
                 symbols=None,
                 channels=None,
                 subscription=None,
                 config: Union[Config, dict, str] = None,
                 callbacks=None,
                 max_depth=None,
                 book_interval=1000,
                 snapshot_interval=False,
                 checksum_validation=False,
                 cross_check=False,
                 origin=None):
        """
        address: str, or dict
            address to be used to create the connection.
            The address protocol (wss or https) will be used to determine the connection type.
            Use a "str" to pass one single address, or a dict of option/address
        sandbox: bool
            For authenticated channels, run against the sandbox websocket (when True)
        max_depth: int
            Maximum number of levels per side to return in book updates
        book_interval: int
            Number of updates between snapshots. Only applicable when book deltas are enabled.
            Book deltas are enabled by subscribing to the book delta callback.
        snapshot_interval: bool/int
            Number of updates between snapshots. Only applicable when book delta is not enabled.
            Updates between snapshots are not delivered to the client
        checksum_validation: bool
            Toggle checksum validation, when supported by an exchange.
        cross_check: bool
            Toggle a check for a crossed book. Should not be needed on exchanges that support
            checksums or provide message sequence numbers.
        origin: str
            Passed into websocket connect. Sets the origin header.
        """
        if isinstance(config, Config):
            LOG.info(
                '%s: reuse object Config containing the following main keys: %s',
                self.id, ", ".join(config.config.keys()))
            self.config = config
        else:
            LOG.info('%s: create Config from type: %r', self.id, type(config))
            self.config = Config(config)

        self.subscription = defaultdict(set)
        self.address = address
        self.book_update_interval = book_interval
        self.snapshot_interval = snapshot_interval
        self.cross_check = cross_check
        self.updates = defaultdict(int)
        self.do_deltas = False
        self.symbols = []
        self.normalized_symbols = []
        self.channels = []
        self.max_depth = max_depth
        self.previous_book = defaultdict(dict)
        self.origin = origin
        self.checksum_validation = checksum_validation
        self.ws_defaults = {
            'ping_interval': 10,
            'ping_timeout': None,
            'max_size': 2**23,
            'max_queue': None,
            'origin': self.origin
        }
        self.key_id = os.environ.get(f'CF_{self.id}_KEY_ID') or self.config[
            self.id.lower()].key_id
        self.key_secret = os.environ.get(
            f'CF_{self.id}_KEY_SECRET') or self.config[
                self.id.lower()].key_secret
        self._feed_config = defaultdict(list)

        load_exchange_symbol_mapping(self.id, key_id=self.key_id)

        if subscription is not None and (symbols is not None
                                         or channels is not None):
            raise ValueError(
                "Use subscription, or channels and symbols, not both")

        if subscription is not None:
            for channel in subscription:
                chan = feed_to_exchange(self.id, channel)
                if is_authenticated_channel(channel):
                    if not self.key_id or not self.key_secret:
                        raise ValueError(
                            "Authenticated channel subscribed to, but no auth keys provided"
                        )
                self.normalized_symbols.extend(subscription[channel])
                self.subscription[chan].update([
                    symbol_std_to_exchange(symbol, self.id)
                    for symbol in subscription[channel]
                ])
                self._feed_config[channel].extend(self.normalized_symbols)

        if symbols:
            self.normalized_symbols = symbols
            self.symbols = [
                symbol_std_to_exchange(symbol, self.id) for symbol in symbols
            ]
        if channels:
            self.channels = list(
                set([feed_to_exchange(self.id, chan) for chan in channels]))
            [
                self._feed_config[channel].extend(self.normalized_symbols)
                for channel in channels
            ]
            if any(is_authenticated_channel(chan) for chan in channels):
                if not self.key_id or not self.key_secret:
                    raise ValueError(
                        "Authenticated channel subscribed to, but no auth keys provided"
                    )
        self._feed_config = dict(self._feed_config)

        self.l3_book = {}
        self.l2_book = {}
        self.callbacks = {
            FUNDING: Callback(None),
            FUTURES_INDEX: Callback(None),
            L2_BOOK: Callback(None),
            L3_BOOK: Callback(None),
            LIQUIDATIONS: Callback(None),
            OPEN_INTEREST: Callback(None),
            MARKET_INFO: Callback(None),
            TICKER: Callback(None),
            TRADES: Callback(None),
            TRANSACTIONS: Callback(None),
            VOLUME: Callback(None),
            CANDLES: Callback(None),
            ORDER_INFO: Callback(None)
        }

        if callbacks:
            for cb_type, cb_func in callbacks.items():
                self.callbacks[cb_type] = cb_func
                if cb_type == BOOK_DELTA:
                    self.do_deltas = True

        for key, callback in self.callbacks.items():
            if not isinstance(callback, list):
                self.callbacks[key] = [callback]
Exemple #4
0
def test_blockchain_symbol_conversions():
    load_exchange_symbol_mapping(BLOCKCHAIN)
    for _, symbol in blockchain_symbols().items():
        assert symbol_exchange_to_std(symbol) == symbol_std_to_exchange(
            symbol, BLOCKCHAIN)
Exemple #5
0
def test_bitcoincom_symbol_conversions():
    load_exchange_symbol_mapping(BITCOINCOM)
    for _, symbol in bitcoincom_symbols().items():
        std = symbol_exchange_to_std(symbol)
        assert symbol == symbol_std_to_exchange(std, BITCOINCOM)
Exemple #6
0
def test_bitstamp_symbol_conversions():
    load_exchange_symbol_mapping(BITSTAMP)
    for _, symbol in bitstamp_symbols().items():
        std = symbol_exchange_to_std(symbol)
        assert symbol == symbol_std_to_exchange(std, BITSTAMP)
Exemple #7
0
def test_gemini_symbol_conversions():
    load_exchange_symbol_mapping(GEMINI)
    for normalized, symbol in gemini_symbols().items():
        std = symbol_exchange_to_std(symbol)
        assert symbol == symbol_std_to_exchange(std, GEMINI)
        assert normalized == std
Exemple #8
0
def test_hitbtc_symbol_conversions():
    load_exchange_symbol_mapping(HITBTC)
    for _, symbol in hitbtc_symbols().items():
        std = symbol_exchange_to_std(symbol)
        assert symbol == symbol_std_to_exchange(std, HITBTC)
Exemple #9
0
def test_bitfinex_symbol_conversions():
    load_exchange_symbol_mapping(BITFINEX)
    for _, symbol in bitfinex_symbols().items():
        std = symbol_exchange_to_std(symbol)
        assert symbol == symbol_std_to_exchange(std, BITFINEX)
Exemple #10
0
def test_poloniex_symbol_conversions():
    load_exchange_symbol_mapping(POLONIEX)
    for _, symbol in poloniex_symbols().items():
        std = symbol_exchange_to_std(symbol)
        assert symbol == symbol_std_to_exchange(std, POLONIEX)
Exemple #11
0
def test_coinbase_symbol_conversions():
    load_exchange_symbol_mapping(COINBASE)
    for _, symbol in coinbase_symbols().items():
        assert symbol_exchange_to_std(symbol) == symbol_std_to_exchange(
            symbol, COINBASE)
Exemple #12
0
    def __init__(self,
                 address: Union[dict, str],
                 symbols=None,
                 channels=None,
                 subscription=None,
                 config: Union[Config, dict, str] = None,
                 callbacks=None,
                 max_depth=None,
                 book_interval=1000,
                 snapshot_interval=False,
                 checksum_validation=False,
                 cross_check=False,
                 origin=None):
        """
        max_depth: int
            Maximum number of levels per side to return in book updates
        book_interval: int
            Number of updates between snapshots. Only applicable when book deltas are enabled.
            Book deltas are enabled by subscribing to the book delta callback.
        snapshot_interval: bool/int
            Number of updates between snapshots. Only applicable when book delta is not enabled.
            Updates between snapshots are not delivered to the client
        checksum_validation: bool
            Toggle checksum validation, when supported by an exchange.
        cross_check: bool
            Toggle a check for a crossed book. Should not be needed on exchanges that support
            checksums or provide message sequence numbers.
        origin: str
            Passed into websocket connect. Sets the origin header.
        """
        if isinstance(config, Config):
            self.config = config
        else:
            self.config = Config(config)
        self.subscription = defaultdict(set)
        self.address = address
        self.book_update_interval = book_interval
        self.snapshot_interval = snapshot_interval
        self.cross_check = cross_check
        self.updates = defaultdict(int)
        self.do_deltas = False
        self.symbols = []
        self.normalized_symbols = []
        self.channels = []
        self.max_depth = max_depth
        self.previous_book = defaultdict(dict)
        self.origin = origin
        self.checksum_validation = checksum_validation
        self.ws_defaults = {
            'ping_interval': 10,
            'ping_timeout': None,
            'max_size': 2**23,
            'max_queue': None,
            'origin': self.origin
        }
        key_id = self.config[self.id.lower()].key_id
        load_exchange_symbol_mapping(self.id, key_id=key_id)

        if subscription is not None and (symbols is not None
                                         or channels is not None):
            raise ValueError(
                "Use subscription, or channels and symbols, not both")

        if subscription is not None:
            for channel in subscription:
                chan = feed_to_exchange(self.id, channel)
                self.subscription[chan].update([
                    symbol_std_to_exchange(symbol, self.id)
                    for symbol in subscription[channel]
                ])
                self.normalized_symbols.extend(self.subscription[chan])

        if symbols:
            self.normalized_symbols = symbols
            self.symbols = [
                symbol_std_to_exchange(symbol, self.id) for symbol in symbols
            ]
        if channels:
            self.channels = list(
                set([feed_to_exchange(self.id, chan) for chan in channels]))

        self.l3_book = {}
        self.l2_book = {}
        self.callbacks = {
            FUNDING: Callback(None),
            FUTURES_INDEX: Callback(None),
            L2_BOOK: Callback(None),
            L3_BOOK: Callback(None),
            LIQUIDATIONS: Callback(None),
            OPEN_INTEREST: Callback(None),
            MARKET_INFO: Callback(None),
            TICKER: Callback(None),
            TRADES: Callback(None),
            TRANSACTIONS: Callback(None),
            VOLUME: Callback(None)
        }

        if callbacks:
            for cb_type, cb_func in callbacks.items():
                self.callbacks[cb_type] = cb_func
                if cb_type == BOOK_DELTA:
                    self.do_deltas = True

        for key, callback in self.callbacks.items():
            if not isinstance(callback, list):
                self.callbacks[key] = [callback]