Beispiel #1
0
 def __init__(self,
              ascend_ex_api_key: str,
              ascend_ex_secret_key: str,
              trading_pairs: Optional[List[str]] = None,
              trading_required: bool = True
              ):
     """
     :param ascend_ex_api_key: The API key to connect to private AscendEx APIs.
     :param ascend_ex_secret_key: The API secret.
     :param trading_pairs: The market trading pairs which to track order book data.
     :param trading_required: Whether actual trading is needed.
     """
     super().__init__()
     self._trading_required = trading_required
     self._trading_pairs = trading_pairs
     self._throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
     self._order_book_tracker = AscendExOrderBookTracker(self._throttler, trading_pairs=trading_pairs)
     self._ascend_ex_auth = AscendExAuth(ascend_ex_api_key, ascend_ex_secret_key)
     self._user_stream_tracker = AscendExUserStreamTracker(self._throttler, self._ascend_ex_auth, trading_pairs)
     self._ev_loop = asyncio.get_event_loop()
     self._shared_client = None
     self._poll_notifier = asyncio.Event()
     self._last_timestamp = 0
     self._in_flight_orders = {}  # Dict[client_order_id:str, AscendExInFlightOrder]
     self._order_not_found_records = {}  # Dict[client_order_id:str, count:int]
     self._trading_rules = {}  # Dict[trading_pair:str, AscendExTradingRule]
     self._status_polling_task = None
     self._user_stream_event_listener_task = None
     self._trading_rules_polling_task = None
     self._last_poll_timestamp = 0
     self._account_group = None  # required in order to make post requests
     self._account_uid = None  # required in order to produce deterministic order ids
     self._throttler = AsyncThrottler(rate_limits=CONSTANTS.RATE_LIMITS)
Beispiel #2
0
 def setUp(self) -> None:
     super().setUp()
     self.throttler = AsyncThrottler(rate_limits=self.rate_limits)
     self._req_counters: Dict[str, int] = {
         limit.limit_id: 0
         for limit in self.rate_limits
     }
 def __init__(self, wazirx_auth: WazirxAuth):
     super().__init__()
     self._wazirx_auth: WazirxAuth = wazirx_auth
     self._last_recv_time: float = 0
     self._auth_successful_event = asyncio.Event()
     self._throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
     self._shared_http_client = None
Beispiel #4
0
 def __init__(self,
              wazirx_api_key: str,
              wazirx_secret_key: str,
              trading_pairs: Optional[List[str]] = None,
              trading_required: bool = True):
     """
     :param wazirx_api_key: The API key to connect to private Wazirx APIs.
     :param wazirx_secret_key: The API secret.
     :param trading_pairs: The market trading pairs which to track order book data.
     :param trading_required: Whether actual trading is needed.
     """
     super().__init__()
     self._trading_required = trading_required
     self._trading_pairs = trading_pairs
     self._wazirx_auth = WazirxAuth(wazirx_api_key, wazirx_secret_key)
     self._order_book_tracker = WazirxOrderBookTracker(
         trading_pairs=trading_pairs)
     self._user_stream_tracker = WazirxUserStreamTracker(
         self._wazirx_auth, trading_pairs)
     self._ev_loop = asyncio.get_event_loop()
     self._shared_client = None
     self._poll_notifier = asyncio.Event()
     self._last_timestamp = 0
     self._in_flight_orders = {
     }  # Dict[client_order_id:str, WazirxInFlightOrder]
     self._order_not_found_records = {
     }  # Dict[client_order_id:str, count:int]
     self._trading_rules = {}  # Dict[trading_pair:str, TradingRule]
     self._status_polling_task = None
     self._user_stream_event_listener_task = None
     self._trading_rules_polling_task = None
     self._last_poll_timestamp = 0
     self._throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
Beispiel #5
0
    def __init__(self,
                 mexc_api_key: str,
                 mexc_secret_key: str,
                 poll_interval: float = 5.0,
                 order_book_tracker_data_source_type: OrderBookTrackerDataSourceType = OrderBookTrackerDataSourceType.EXCHANGE_API,
                 trading_pairs: Optional[List[str]] = None,
                 trading_required: bool = True):

        super().__init__()
        self._throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self._shared_client = aiohttp.ClientSession()
        self._async_scheduler = AsyncCallScheduler(call_interval=0.5)
        self._data_source_type = order_book_tracker_data_source_type
        self._ev_loop = asyncio.get_event_loop()
        self._mexc_auth = MexcAuth(api_key=mexc_api_key, secret_key=mexc_secret_key)
        self._in_flight_orders = {}
        self._last_poll_timestamp = 0
        self._last_timestamp = 0
        self._order_book_tracker = MexcOrderBookTracker(
            throttler=self._throttler, trading_pairs=trading_pairs, shared_client=self._shared_client)
        self._poll_notifier = asyncio.Event()
        self._poll_interval = poll_interval
        self._status_polling_task = None
        self._trading_required = trading_required
        self._trading_rules = {}
        self._trading_rules_polling_task = None
        self._user_stream_tracker = MexcUserStreamTracker(throttler=self._throttler,
                                                          mexc_auth=self._mexc_auth,
                                                          trading_pairs=trading_pairs,
                                                          shared_client=self._shared_client)
        self._user_stream_tracker_task = None
        self._user_stream_event_listener_task = None
 def setUp(self) -> None:
     super().setUp()
     self.throttler = AsyncThrottler(rate_limits=self.rate_limits)
     self._req_counters: Dict[str, int] = {
         limit.limit_id: 0
         for limit in self.rate_limits
     }
     self.client_config_map = ClientConfigAdapter(ClientConfigMap())
    def __init__(self,
                 client_config_map: "ClientConfigAdapter",
                 ndax_uid: str,
                 ndax_api_key: str,
                 ndax_secret_key: str,
                 ndax_account_name: str,
                 trading_pairs: Optional[List[str]] = None,
                 trading_required: bool = True,
                 domain: Optional[str] = None):
        """
        :param ndax_uid: User ID of the account
        :param ndax_api_key: The API key to connect to private NDAX APIs.
        :param ndax_secret_key: The API secret.
        :param ndax_account_name: The name of the account associated to the user account.
        :param trading_pairs: The market trading pairs which to track order book data.
        :param trading_required: Whether actual trading is needed.
        """
        super().__init__(client_config_map)
        self._trading_required = trading_required
        self._trading_pairs = trading_pairs
        self._auth = NdaxAuth(uid=ndax_uid,
                              api_key=ndax_api_key,
                              secret_key=ndax_secret_key,
                              account_name=ndax_account_name)
        self._throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self._shared_client = aiohttp.ClientSession()
        self._set_order_book_tracker(
            NdaxOrderBookTracker(throttler=self._throttler,
                                 shared_client=self._shared_client,
                                 trading_pairs=trading_pairs,
                                 domain=domain))
        self._user_stream_tracker = NdaxUserStreamTracker(
            throttler=self._throttler,
            shared_client=self._shared_client,
            auth_assistant=self._auth,
            domain=domain)
        self._domain = domain
        self._ev_loop = asyncio.get_event_loop()
        self._poll_notifier = asyncio.Event()
        self._last_timestamp = 0
        self._in_flight_orders = {}
        self._order_not_found_records = {
        }  # Dict[client_order_id:str, count:int]
        self._trading_rules = {}  # Dict[trading_pair:str, TradingRule]
        self._last_poll_timestamp = 0

        self._status_polling_task = None
        self._user_stream_tracker_task = None
        self._user_stream_event_listener_task = None
        self._trading_rules_polling_task = None

        self._account_id = None
 def setUp(self) -> None:
     super().setUp()
     self.mocking_assistant = NetworkMockingAssistant()
     self.throttler = AsyncThrottler(
         build_rate_limits_by_tier(self.api_tier))
     self.data_source = KrakenAPIOrderBookDataSource(
         self.throttler, trading_pairs=[self.trading_pair])
Beispiel #9
0
    def setUp(self) -> None:
        super().setUp()

        self.ev_loop = asyncio.get_event_loop()

        self.base_asset = "BTC"
        self.quote_asset = "USDT"
        self.trading_pair = f"{self.base_asset}-{self.quote_asset}"
        self.ex_trading_pair = f"{self.base_asset}/{self.quote_asset}"

        self.log_records = []
        self.listening_task = None
        self.async_task: Optional[asyncio.Task] = None

        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.api_factory = build_api_factory(throttler=self.throttler)

        self.data_source = AscendExAPIOrderBookDataSource(
            api_factory=self.api_factory,
            throttler=self.throttler,
            trading_pairs=[self.trading_pair])
        self.data_source.logger().setLevel(1)
        self.data_source.logger().addHandler(self)

        self.mocking_assistant = NetworkMockingAssistant()
        self.resume_test_event = asyncio.Event()

        AscendExAPIOrderBookDataSource._trading_pair_symbol_map = bidict(
            {self.ex_trading_pair: f"{self.base_asset}-{self.quote_asset}"})
    def setUp(self) -> None:
        super().setUp()
        self.log_records = []
        self.listening_task: Optional[asyncio.Task] = None
        self.mocking_assistant = NetworkMockingAssistant()

        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.mock_time_provider = MagicMock()
        self.mock_time_provider.time.return_value = 1000
        self.auth = KucoinAuth(
            self.api_key,
            self.api_passphrase,
            self.api_secret_key,
            time_provider=self.mock_time_provider)

        client_config_map = ClientConfigAdapter(ClientConfigMap())
        self.connector = KucoinExchange(
            client_config_map=client_config_map,
            kucoin_api_key="",
            kucoin_passphrase="",
            kucoin_secret_key="",
            trading_pairs=[],
            trading_required=False)

        self.data_source = KucoinAPIUserStreamDataSource(
            auth=self.auth,
            trading_pairs=[self.trading_pair],
            connector=self.connector,
            api_factory=self.connector._web_assistants_factory)

        self.data_source.logger().setLevel(1)
        self.data_source.logger().addHandler(self)
 def setUpClass(cls):
     cls.ev_loop: asyncio.AbstractEventLoop = asyncio.get_event_loop()
     cls.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
     cls.order_book_tracker: GateIoOrderBookTracker = GateIoOrderBookTracker(
         cls.throttler, cls.trading_pairs)
     cls.order_book_tracker.start()
     cls.ev_loop.run_until_complete(cls.wait_til_tracker_ready())
    def test_rest_assistant_call_with_pre_and_post_processing(self, mocked_api):
        url = "https://www.test.com/url"
        resp = {"one": 1}
        pre_processor_ran = False
        post_processor_ran = False
        mocked_api.get(url, body=json.dumps(resp).encode())

        class PreProcessor(RESTPreProcessorBase):
            async def pre_process(self, request: RESTRequest) -> RESTRequest:
                nonlocal pre_processor_ran
                pre_processor_ran = True
                return request

        class PostProcessor(RESTPostProcessorBase):
            async def post_process(self, response: RESTResponse) -> RESTResponse:
                nonlocal post_processor_ran
                post_processor_ran = True
                return response

        pre_processors = [PreProcessor()]
        post_processors = [PostProcessor()]
        connection = RESTConnection(aiohttp.ClientSession())
        assistant = RESTAssistant(
            connection=connection,
            throttler=AsyncThrottler(rate_limits=[]),
            rest_pre_processors=pre_processors,
            rest_post_processors=post_processors)
        req = RESTRequest(method=RESTMethod.GET, url=url)

        ret = self.async_run_with_timeout(assistant.call(req))
        ret_json = self.async_run_with_timeout(ret.json())

        self.assertEqual(resp, ret_json)
        self.assertTrue(pre_processor_ran)
        self.assertTrue(post_processor_ran)
Beispiel #13
0
    def test_sending_messages_increment_message_number(self, mock_ws):
        sent_messages = []
        throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        mock_ws.return_value = self.mocking_assistant.create_websocket_mock()
        mock_ws.return_value.send_json.side_effect = lambda sent_message: sent_messages.append(
            sent_message)

        adaptor = NdaxWebSocketAdaptor(throttler,
                                       websocket=mock_ws.return_value)
        payload = {}
        self.async_run_with_timeout(
            adaptor.send_request(endpoint_name=CONSTANTS.WS_PING_REQUEST,
                                 payload=payload,
                                 limit_id=CONSTANTS.WS_PING_ID))
        self.async_run_with_timeout(
            adaptor.send_request(endpoint_name=CONSTANTS.WS_PING_REQUEST,
                                 payload=payload,
                                 limit_id=CONSTANTS.WS_PING_ID))
        self.async_run_with_timeout(
            adaptor.send_request(endpoint_name=CONSTANTS.WS_ORDER_BOOK_CHANNEL,
                                 payload=payload))
        self.assertEqual(3, len(sent_messages))

        message = sent_messages[0]
        self.assertEqual(1, message.get('i'))
        message = sent_messages[1]
        self.assertEqual(2, message.get('i'))
        message = sent_messages[2]
        self.assertEqual(3, message.get('i'))
    def setUp(self) -> None:
        super().setUp()
        self.log_records = []
        self.listening_task: Optional[asyncio.Task] = None
        self.mocking_assistant = NetworkMockingAssistant()

        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.mock_time_provider = MagicMock()
        self.mock_time_provider.time.return_value = 1000
        self.auth = KucoinAuth(self.api_key,
                               self.api_passphrase,
                               self.api_secret_key,
                               time_provider=self.mock_time_provider)
        self.time_synchronizer = TimeSynchronizer()
        self.time_synchronizer.add_time_offset_ms_sample(0)

        self.api_factory = web_utils.build_api_factory(
            throttler=self.throttler,
            time_synchronizer=self.time_synchronizer,
            auth=self.auth)

        self.data_source = KucoinAPIUserStreamDataSource(
            throttler=self.throttler, api_factory=self.api_factory)

        self.data_source.logger().setLevel(1)
        self.data_source.logger().addHandler(self)
Beispiel #15
0
    def test_send_subscription_message(self, ws_connect_mock):
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        throttler = AsyncThrottler(Constants.RATE_LIMITS)
        websocket = CoinzoomWebsocket(throttler=throttler)
        message = {Constants.WS_SUB["TRADES"]: {'symbol': "BTC/USDT"}}

        self.async_run_with_timeout(websocket.connect())
        self.async_run_with_timeout(websocket.subscribe(message))
        self.async_run_with_timeout(websocket.unsubscribe(message))

        sent_requests = self.mocking_assistant.text_messages_sent_through_websocket(
            ws_connect_mock.return_value)
        sent_subscribe_message = json.loads(sent_requests[0])
        expected_subscribe_message = {
            "TradeSummaryRequest": {
                "action": "subscribe",
                "symbol": "BTC/USDT"
            }
        }
        self.assertEquals(expected_subscribe_message, sent_subscribe_message)
        sent_unsubscribe_message = json.loads(sent_requests[0])
        expected_unsubscribe_message = {
            "TradeSummaryRequest": {
                "action": "subscribe",
                "symbol": "BTC/USDT"
            }
        }
        self.assertEquals(expected_unsubscribe_message,
                          sent_unsubscribe_message)
Beispiel #16
0
 def setUp(self) -> None:
     super().setUp()
     self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
     self.auth = KucoinAuth(self.api_key, self.api_passphrase,
                            self.api_secret_key)
     self.ob_data_source = KucoinAPIOrderBookDataSource(
         self.throttler, [self.trading_pair], self.auth)
    def setUp(self) -> None:
        super().setUp()
        self.log_records = []
        self.listening_task: Optional[asyncio.Task] = None
        self.mocking_assistant = NetworkMockingAssistant()

        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.mock_time_provider = MagicMock()
        self.mock_time_provider.time.return_value = 1000
        self.auth = GateIoAuth(api_key=self.api_key,
                               secret_key=self.api_secret_key,
                               time_provider=self.mock_time_provider)
        self.time_synchronizer = TimeSynchronizer()
        self.time_synchronizer.add_time_offset_ms_sample(0)

        client_config_map = ClientConfigAdapter(ClientConfigMap())
        self.connector = GateIoExchange(client_config_map=client_config_map,
                                        gate_io_api_key="",
                                        gate_io_secret_key="",
                                        trading_pairs=[],
                                        trading_required=False)
        self.connector._web_assistants_factory._auth = self.auth

        self.data_source = GateIoAPIUserStreamDataSource(
            self.auth,
            trading_pairs=[self.trading_pair],
            connector=self.connector,
            api_factory=self.connector._web_assistants_factory)

        self.data_source.logger().setLevel(1)
        self.data_source.logger().addHandler(self)

        self.connector._set_trading_pair_symbol_map(
            bidict({self.ex_trading_pair: self.trading_pair}))
Beispiel #18
0
    def test_get_ws_assistant(self):
        factory = WebAssistantsFactory(throttler=AsyncThrottler(
            rate_limits=[]))

        ws_assistant = self.async_run_with_timeout(factory.get_ws_assistant())

        self.assertIsInstance(ws_assistant, WSAssistant)
    def test_send_subscription_message(self, request_id_mock, ws_connect_mock):
        request_id_mock.return_value = 1234567899
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        throttler = AsyncThrottler(Constants.RATE_LIMITS)
        websocket = AltmarketsWebsocket(throttler=throttler)
        message = [Constants.WS_SUB["TRADES"].format(trading_pair="btcusdt")]

        self.async_run_with_timeout(websocket.connect())
        self.async_run_with_timeout(websocket.subscribe(message))
        self.async_run_with_timeout(websocket.unsubscribe(message))

        sent_requests = self.mocking_assistant.text_messages_sent_through_websocket(
            ws_connect_mock.return_value)
        sent_subscribe_message = json.loads(sent_requests[0])
        expected_subscribe_message = {
            "event": "subscribe",
            "id": 1234567899,
            "streams": ['btcusdt.trades']
        }
        self.assertEquals(expected_subscribe_message, sent_subscribe_message)
        sent_unsubscribe_message = json.loads(sent_requests[1])
        expected_unsubscribe_message = {
            "event": "unsubscribe",
            "id": 1234567899,
            "streams": ['btcusdt.trades']
        }
        self.assertEquals(expected_unsubscribe_message,
                          sent_unsubscribe_message)
Beispiel #20
0
async def api_call_with_retries(request: CoinflexRESTRequest,
                                rest_assistant: RESTAssistant,
                                throttler: AsyncThrottler,
                                logger: logging.Logger = None,
                                try_count: int = 0) -> Dict[str, Any]:

    async with throttler.execute_task(limit_id=request.throttler_limit_id):
        http_status, resp, request_errors = await rest_response_with_errors(rest_assistant, request)

    if isinstance(resp, dict):
        _extract_error_from_response(resp)

    if request_errors or resp is None:
        if try_count < CONSTANTS.API_MAX_RETRIES and not request.disable_retries:
            try_count += 1
            time_sleep = retry_sleep_time(try_count)

            suppress_msgs = ['Forbidden']

            err_msg = (f"Error fetching data from {request.url}. HTTP status is {http_status}. "
                       f"Retrying in {time_sleep:.0f}s. {resp or ''}")

            if (resp is not None and resp not in suppress_msgs) or try_count > 1:
                if logger:
                    logger.network(err_msg)
                else:
                    print(err_msg)
            elif logger:
                logger.debug(err_msg, exc_info=True)
            await asyncio.sleep(time_sleep)
            return await api_call_with_retries(request=request, rest_assistant=rest_assistant, throttler=throttler,
                                               logger=logger, try_count=try_count)
        else:
            raise CoinflexAPIError({"errors": resp, "status": http_status})
    return resp
Beispiel #21
0
 def setUp(self) -> None:
     super().setUp()
     self.rest_assistant = self.async_run_with_timeout(
         web_utils.build_api_factory().get_rest_assistant())
     self.logger.setLevel(1)
     self.logger.addHandler(self)
     self.log_records = []
     self.throttler = AsyncThrottler(rate_limits=CONSTANTS.RATE_LIMITS)
    def test_close(self):
        throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        ws = AsyncMock()

        adaptor = NdaxWebSocketAdaptor(throttler, websocket=ws)
        asyncio.get_event_loop().run_until_complete(adaptor.close())

        self.assertEquals(1, ws.close.await_count)
 def setUp(self) -> None:
     super().setUp()
     self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
     self.auth = KucoinAuth(self.api_key, self.api_passphrase,
                            self.api_secret_key)
     self.data_source = KucoinAPIUserStreamDataSource(
         self.throttler, self.auth)
     self.mocking_assistant = NetworkMockingAssistant()
Beispiel #24
0
 def setUp(self) -> None:
     super().setUp()
     self.mocking_assistant = NetworkMockingAssistant()
     altmarkets_auth = AltmarketsAuth(api_key="someKey",
                                      secret_key="someSecret")
     self.data_source = AltmarketsAPIUserStreamDataSource(
         AsyncThrottler(Constants.RATE_LIMITS),
         altmarkets_auth=altmarkets_auth,
         trading_pairs=[self.trading_pair])
 def __init__(self,
              auth: Optional[AltmarketsAuth] = None,
              throttler: Optional[AsyncThrottler] = None):
     self._auth: Optional[AltmarketsAuth] = auth
     self._isPrivate = True if self._auth is not None else False
     self._WS_URL = Constants.WS_PRIVATE_URL if self._isPrivate else Constants.WS_PUBLIC_URL
     self._client: Optional[websockets.WebSocketClientProtocol] = None
     self._is_subscribed = False
     self._throttler = throttler or AsyncThrottler(Constants.RATE_LIMITS)
 def setUpClass(cls) -> None:
     super().setUpClass()
     cls.base_asset = "COINALPHA"
     cls.quote_asset = "HBOT"
     cls.trading_pair = f"{cls.base_asset}-{cls.quote_asset}"
     cls.api_key = "testKey"
     cls.api_secret_key = "testSecretKey"
     cls.username = "******"
     cls.throttler = AsyncThrottler(Constants.RATE_LIMITS)
    def test_close(self, mock_ws):
        throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        mock_ws.return_value = self.mocking_assistant.create_websocket_mock()

        adaptor = NdaxWebSocketAdaptor(throttler,
                                       websocket=mock_ws.return_value)
        asyncio.get_event_loop().run_until_complete(adaptor.close())

        self.assertEquals(1, mock_ws.return_value.close.await_count)
Beispiel #28
0
 def setUp(self) -> None:
     super().setUp()
     self.mocking_assistant = NetworkMockingAssistant()
     self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
     not_a_real_secret = "kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F1huXg=="
     kraken_auth = KrakenAuth(api_key="someKey",
                              secret_key=not_a_real_secret)
     self.data_source = KrakenAPIUserStreamDataSource(
         self.throttler, kraken_auth)
Beispiel #29
0
    def test_close(self, mock_ws):
        throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        mock_ws.return_value = self.mocking_assistant.create_websocket_mock()

        adaptor = NdaxWebSocketAdaptor(throttler,
                                       websocket=mock_ws.return_value)
        self.async_run_with_timeout(adaptor.close())

        self.assertEquals(1, mock_ws.return_value.close.await_count)
    def test_receive_message(self):
        throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        ws = AsyncMock()
        ws.recv.return_value = 'test message'

        adaptor = NdaxWebSocketAdaptor(throttler, websocket=ws)
        received_message = asyncio.get_event_loop().run_until_complete(adaptor.recv())

        self.assertEqual('test message', received_message)