From 9e566bbc5a28d4006a974af62b488ec971a03e10 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Tue, 7 Mar 2023 15:28:02 +0100 Subject: [PATCH] Switch from max-line-length=130 to more standard max-line-length=120 in .pylintrc. --- .pylintrc | 2 +- bfxapi/tests/test_labeler.py | 3 +- bfxapi/tests/test_rest_serializers.py | 3 +- bfxapi/tests/test_websocket_serializers.py | 3 +- .../websocket/client/bfx_websocket_bucket.py | 28 +- .../websocket/client/bfx_websocket_client.py | 44 +- bfxapi/websocket/serializers.py | 574 ++++++++++-------- 7 files changed, 372 insertions(+), 285 deletions(-) diff --git a/.pylintrc b/.pylintrc index 6a9303c..7798ffd 100644 --- a/.pylintrc +++ b/.pylintrc @@ -17,7 +17,7 @@ disable= [FORMAT] -max-line-length=130 +max-line-length=120 good-names=id,on,pl,t,A,B,C,D,E,F diff --git a/bfxapi/tests/test_labeler.py b/bfxapi/tests/test_labeler.py index a586380..5750d9c 100644 --- a/bfxapi/tests/test_labeler.py +++ b/bfxapi/tests/test_labeler.py @@ -26,7 +26,8 @@ class TestLabeler(unittest.TestCase): msg="_Serializer::get_labels() should return the right list of labels.") with self.assertRaises(LabelerSerializerException, - msg="_Serializer should raise LabelerSerializerException if given fewer arguments than the serializer labels."): + msg="_Serializer should raise LabelerSerializerException if given " + + "fewer arguments than the serializer labels."): serializer.parse(5, 65.0, "X") def test_generate_recursive_serializer(self): diff --git a/bfxapi/tests/test_rest_serializers.py b/bfxapi/tests/test_rest_serializers.py index 17c3d98..0cf43b5 100644 --- a/bfxapi/tests/test_rest_serializers.py +++ b/bfxapi/tests/test_rest_serializers.py @@ -13,7 +13,8 @@ class TestRestSerializers(unittest.TestCase): f"_Serializer <{serializer.name}>: .klass field must be a subclass of _Type (got {serializer.klass}).") self.assertListEqual(serializer.get_labels(), list(serializer.klass.__annotations__), - f"_Serializer <{serializer.name}> and _Type <{serializer.klass.__name__}> must have matching labels and fields.") + f"_Serializer <{serializer.name}> and _Type <{serializer.klass.__name__}> " + + "must have matching labels and fields.") if __name__ == "__main__": unittest.main() diff --git a/bfxapi/tests/test_websocket_serializers.py b/bfxapi/tests/test_websocket_serializers.py index 111cde4..56708f4 100644 --- a/bfxapi/tests/test_websocket_serializers.py +++ b/bfxapi/tests/test_websocket_serializers.py @@ -13,7 +13,8 @@ class TestWebsocketSerializers(unittest.TestCase): f"_Serializer <{serializer.name}>: .klass field must be a subclass of _Type (got {serializer.klass}).") self.assertListEqual(serializer.get_labels(), list(serializer.klass.__annotations__), - f"_Serializer <{serializer.name}> and _Type <{serializer.klass.__name__}> must have matching labels and fields.") + f"_Serializer <{serializer.name}> and _Type <{serializer.klass.__name__}> " + + "must have matching labels and fields.") if __name__ == "__main__": unittest.main() diff --git a/bfxapi/websocket/client/bfx_websocket_bucket.py b/bfxapi/websocket/client/bfx_websocket_bucket.py index 2579c11..72c3419 100644 --- a/bfxapi/websocket/client/bfx_websocket_bucket.py +++ b/bfxapi/websocket/client/bfx_websocket_bucket.py @@ -52,17 +52,23 @@ class BfxWebsocketBucket: async for message in websocket: message = json.loads(message) - if isinstance(message, dict) and message["event"] == "subscribed" and (chan_id := message["chanId"]): - self.pendings = [ pending for pending in self.pendings if pending["subId"] != message["subId"] ] - self.subscriptions[chan_id] = message - self.event_emitter.emit("subscribed", message) - elif isinstance(message, dict) and message["event"] == "unsubscribed" and (chan_id := message["chanId"]): - if message["status"] == "OK": - del self.subscriptions[chan_id] - elif isinstance(message, dict) and message["event"] == "error": - self.event_emitter.emit("wss-error", message["code"], message["msg"]) - elif isinstance(message, list) and (chan_id := message[0]) and message[1] != _HEARTBEAT: - self.handler.handle(self.subscriptions[chan_id], *message[1:]) + if isinstance(message, dict): + if message["event"] == "subscribed" and (chan_id := message["chanId"]): + self.pendings = \ + [ pending for pending in self.pendings if pending["subId"] != message["subId"] ] + + self.subscriptions[chan_id] = message + + self.event_emitter.emit("subscribed", message) + elif message["event"] == "unsubscribed" and (chan_id := message["chanId"]): + if message["status"] == "OK": + del self.subscriptions[chan_id] + elif message["event"] == "error": + self.event_emitter.emit("wss-error", message["code"], message["msg"]) + + if isinstance(message, list): + if (chan_id := message[0]) and message[1] != _HEARTBEAT: + self.handler.handle(self.subscriptions[chan_id], *message[1:]) except websockets.ConnectionClosedError as error: if error.code == 1006: self.on_open_event.clear() diff --git a/bfxapi/websocket/client/bfx_websocket_client.py b/bfxapi/websocket/client/bfx_websocket_client.py index 7e5f2a6..360f840 100644 --- a/bfxapi/websocket/client/bfx_websocket_client.py +++ b/bfxapi/websocket/client/bfx_websocket_client.py @@ -66,8 +66,8 @@ class BfxWebsocketClient: async def start(self, connections = 5): if connections > BfxWebsocketClient.MAXIMUM_CONNECTIONS_AMOUNT: self.logger.warning(f"It is not safe to use more than {BfxWebsocketClient.MAXIMUM_CONNECTIONS_AMOUNT} " - + f"buckets from the same connection ({connections} in use), the server could momentarily block the " - + "client with <429 Too Many Requests>.") + + f"buckets from the same connection ({connections} in use), the server could momentarily " + + "block the client with <429 Too Many Requests>.") for _ in range(connections): self.on_open_events.append(asyncio.Event()) @@ -109,25 +109,31 @@ class BfxWebsocketClient: async for message in websocket: message = json.loads(message) - if isinstance(message, dict) and message["event"] == "info" and "version" in message: - if BfxWebsocketClient.VERSION != message["version"]: - raise OutdatedClientVersion("Mismatch between the client version and the server version. " - + "Update the library to the latest version to continue (client version: " - + f"{BfxWebsocketClient.VERSION}, server version: {message['version']}).") - elif isinstance(message, dict) and message["event"] == "info" and message["code"] == 20051: - rcvd = websockets.frames.Close(code=1012, reason="Stop/Restart Websocket Server (please reconnect).") + if isinstance(message, dict): + if message["event"] == "info" and "version" in message: + if BfxWebsocketClient.VERSION != message["version"]: + raise OutdatedClientVersion("Mismatch between the client version and the server " + + "version. Update the library to the latest version to continue (client version: " + + f"{BfxWebsocketClient.VERSION}, server version: {message['version']}).") + elif message["event"] == "info" and message["code"] == 20051: + rcvd = websockets.frames.Close(code=1012, + reason="Stop/Restart Websocket Server (please reconnect).") + + raise websockets.ConnectionClosedError(rcvd=rcvd, sent=None) + elif message["event"] == "auth": + if message["status"] != "OK": + raise InvalidAuthenticationCredentials( + "Cannot authenticate with given API-KEY and API-SECRET.") - raise websockets.ConnectionClosedError(rcvd=rcvd, sent=None) - elif isinstance(message, dict) and message["event"] == "auth": - if message["status"] == "OK": self.event_emitter.emit("authenticated", message) self.authentication = True - else: raise InvalidAuthenticationCredentials("Cannot authenticate with given API-KEY and API-SECRET.") - elif isinstance(message, dict) and message["event"] == "error": - self.event_emitter.emit("wss-error", message["code"], message["msg"]) - elif isinstance(message, list) and message[0] == 0 and message[1] != _HEARTBEAT: - self.handler.handle(message[1], message[2]) + elif message["event"] == "error": + self.event_emitter.emit("wss-error", message["code"], message["msg"]) + + if isinstance(message, list): + if message[0] == 0 and message[1] != _HEARTBEAT: + self.handler.handle(message[1], message[2]) class _Delay: BACKOFF_MIN, BACKOFF_MAX = 1.92, 60.0 @@ -171,8 +177,8 @@ class BfxWebsocketClient: delay = _Delay(backoff_factor=1.618) elif isinstance(error, socket.gaierror) and reconnection.status: self.logger.warning(f"Reconnection attempt no.{reconnection.attempts} has failed. " - + f"Next reconnection attempt in ~{round(delay.peek()):.1f} seconds." - + f"(at the moment the client has been offline for {datetime.now() - reconnection.timestamp})") + + f"Next reconnection attempt in ~{round(delay.peek()):.1f} seconds. (at the moment " + + f"the client has been offline for {datetime.now() - reconnection.timestamp})") reconnection = reconnection._replace(attempts=reconnection.attempts + 1) else: raise error diff --git a/bfxapi/websocket/serializers.py b/bfxapi/websocket/serializers.py index ae2f04e..2bcea77 100644 --- a/bfxapi/websocket/serializers.py +++ b/bfxapi/websocket/serializers.py @@ -18,277 +18,349 @@ __serializers__ = [ #region Serializers definition for Websocket Public Channels -TradingPairTicker = generate_labeler_serializer("TradingPairTicker", klass=types.TradingPairTicker, labels=[ - "bid", - "bid_size", - "ask", - "ask_size", - "daily_change", - "daily_change_relative", - "last_price", - "volume", - "high", - "low" -]) +TradingPairTicker = generate_labeler_serializer( + name="TradingPairTicker", + klass=types.TradingPairTicker, + labels=[ + "bid", + "bid_size", + "ask", + "ask_size", + "daily_change", + "daily_change_relative", + "last_price", + "volume", + "high", + "low" + ] +) -FundingCurrencyTicker = generate_labeler_serializer("FundingCurrencyTicker", klass=types.FundingCurrencyTicker, labels=[ - "frr", - "bid", - "bid_period", - "bid_size", - "ask", - "ask_period", - "ask_size", - "daily_change", - "daily_change_relative", - "last_price", - "volume", - "high", - "low", - "_PLACEHOLDER", - "_PLACEHOLDER", - "frr_amount_available" -]) +FundingCurrencyTicker = generate_labeler_serializer( + name="FundingCurrencyTicker", + klass=types.FundingCurrencyTicker, + labels=[ + "frr", + "bid", + "bid_period", + "bid_size", + "ask", + "ask_period", + "ask_size", + "daily_change", + "daily_change_relative", + "last_price", + "volume", + "high", + "low", + "_PLACEHOLDER", + "_PLACEHOLDER", + "frr_amount_available" + ] +) -TradingPairTrade = generate_labeler_serializer("TradingPairTrade", klass=types.TradingPairTrade, labels=[ - "id", - "mts", - "amount", - "price" -]) +TradingPairTrade = generate_labeler_serializer( + name="TradingPairTrade", + klass=types.TradingPairTrade, + labels=[ + "id", + "mts", + "amount", + "price" + ] +) -FundingCurrencyTrade = generate_labeler_serializer("FundingCurrencyTrade", klass=types.FundingCurrencyTrade, labels=[ - "id", - "mts", - "amount", - "rate", - "period" -]) +FundingCurrencyTrade = generate_labeler_serializer( + name="FundingCurrencyTrade", + klass=types.FundingCurrencyTrade, + labels=[ + "id", + "mts", + "amount", + "rate", + "period" + ] +) -TradingPairBook = generate_labeler_serializer("TradingPairBook", klass=types.TradingPairBook, labels=[ - "price", - "count", - "amount" -]) +TradingPairBook = generate_labeler_serializer( + name="TradingPairBook", + klass=types.TradingPairBook, + labels=[ + "price", + "count", + "amount" + ] +) -FundingCurrencyBook = generate_labeler_serializer("FundingCurrencyBook", klass=types.FundingCurrencyBook, labels=[ - "rate", - "period", - "count", - "amount" -]) +FundingCurrencyBook = generate_labeler_serializer( + name="FundingCurrencyBook", + klass=types.FundingCurrencyBook, + labels=[ + "rate", + "period", + "count", + "amount" + ] +) -TradingPairRawBook = generate_labeler_serializer("TradingPairRawBook", klass=types.TradingPairRawBook, labels=[ - "order_id", - "price", - "amount" -]) +TradingPairRawBook = generate_labeler_serializer( + name="TradingPairRawBook", + klass=types.TradingPairRawBook, + labels=[ + "order_id", + "price", + "amount" + ] +) -FundingCurrencyRawBook = generate_labeler_serializer("FundingCurrencyRawBook", klass=types.FundingCurrencyRawBook, labels=[ - "offer_id", - "period", - "rate", - "amount" -]) +FundingCurrencyRawBook = generate_labeler_serializer( + name="FundingCurrencyRawBook", + klass=types.FundingCurrencyRawBook, + labels=[ + "offer_id", + "period", + "rate", + "amount" + ] +) -Candle = generate_labeler_serializer("Candle", klass=types.Candle, labels=[ - "mts", - "open", - "close", - "high", - "low", - "volume" -]) +Candle = generate_labeler_serializer( + name="Candle", + klass=types.Candle, + labels=[ + "mts", + "open", + "close", + "high", + "low", + "volume" + ] +) -DerivativesStatus = generate_labeler_serializer("DerivativesStatus", klass=types.DerivativesStatus, labels=[ - "mts", - "_PLACEHOLDER", - "deriv_price", - "spot_price", - "_PLACEHOLDER", - "insurance_fund_balance", - "_PLACEHOLDER", - "next_funding_evt_timestamp_ms", - "next_funding_accrued", - "next_funding_step", - "_PLACEHOLDER", - "current_funding", - "_PLACEHOLDER", - "_PLACEHOLDER", - "mark_price", - "_PLACEHOLDER", - "_PLACEHOLDER", - "open_interest", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "clamp_min", - "clamp_max" -]) +DerivativesStatus = generate_labeler_serializer( + name="DerivativesStatus", + klass=types.DerivativesStatus, + labels=[ + "mts", + "_PLACEHOLDER", + "deriv_price", + "spot_price", + "_PLACEHOLDER", + "insurance_fund_balance", + "_PLACEHOLDER", + "next_funding_evt_timestamp_ms", + "next_funding_accrued", + "next_funding_step", + "_PLACEHOLDER", + "current_funding", + "_PLACEHOLDER", + "_PLACEHOLDER", + "mark_price", + "_PLACEHOLDER", + "_PLACEHOLDER", + "open_interest", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "clamp_min", + "clamp_max" + ] +) #endregion #region Serializers definition for Websocket Authenticated Channels -Order = generate_labeler_serializer("Order", klass=types.Order, labels=[ - "id", - "gid", - "cid", - "symbol", - "mts_create", - "mts_update", - "amount", - "amount_orig", - "order_type", - "type_prev", - "mts_tif", - "_PLACEHOLDER", - "flags", - "order_status", - "_PLACEHOLDER", - "_PLACEHOLDER", - "price", - "price_avg", - "price_trailing", - "price_aux_limit", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "notify", - "hidden", - "placed_id", - "_PLACEHOLDER", - "_PLACEHOLDER", - "routing", - "_PLACEHOLDER", - "_PLACEHOLDER", - "meta" -]) +Order = generate_labeler_serializer( + name="Order", + klass=types.Order, + labels=[ + "id", + "gid", + "cid", + "symbol", + "mts_create", + "mts_update", + "amount", + "amount_orig", + "order_type", + "type_prev", + "mts_tif", + "_PLACEHOLDER", + "flags", + "order_status", + "_PLACEHOLDER", + "_PLACEHOLDER", + "price", + "price_avg", + "price_trailing", + "price_aux_limit", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "notify", + "hidden", + "placed_id", + "_PLACEHOLDER", + "_PLACEHOLDER", + "routing", + "_PLACEHOLDER", + "_PLACEHOLDER", + "meta" + ] +) -Position = generate_labeler_serializer("Position", klass=types.Position, labels=[ - "symbol", - "status", - "amount", - "base_price", - "margin_funding", - "margin_funding_type", - "pl", - "pl_perc", - "price_liq", - "leverage", - "flag", - "position_id", - "mts_create", - "mts_update", - "_PLACEHOLDER", - "type", - "_PLACEHOLDER", - "collateral", - "collateral_min", - "meta" -]) +Position = generate_labeler_serializer( + name="Position", + klass=types.Position, + labels=[ + "symbol", + "status", + "amount", + "base_price", + "margin_funding", + "margin_funding_type", + "pl", + "pl_perc", + "price_liq", + "leverage", + "flag", + "position_id", + "mts_create", + "mts_update", + "_PLACEHOLDER", + "type", + "_PLACEHOLDER", + "collateral", + "collateral_min", + "meta" + ] +) -Trade = generate_labeler_serializer("Trade", klass=types.Trade, labels=[ - "id", - "symbol", - "mts_create", - "order_id", - "exec_amount", - "exec_price", - "order_type", - "order_price", - "maker", - "fee", - "fee_currency", - "cid" -]) +Trade = generate_labeler_serializer( + name="Trade", + klass=types.Trade, + labels=[ + "id", + "symbol", + "mts_create", + "order_id", + "exec_amount", + "exec_price", + "order_type", + "order_price", + "maker", + "fee", + "fee_currency", + "cid" + ] +) -FundingOffer = generate_labeler_serializer("FundingOffer", klass=types.FundingOffer, labels=[ - "id", - "symbol", - "mts_create", - "mts_update", - "amount", - "amount_orig", - "offer_type", - "_PLACEHOLDER", - "_PLACEHOLDER", - "flags", - "offer_status", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "rate", - "period", - "notify", - "hidden", - "_PLACEHOLDER", - "renew", - "_PLACEHOLDER" -]) +FundingOffer = generate_labeler_serializer( + name="FundingOffer", + klass=types.FundingOffer, + labels=[ + "id", + "symbol", + "mts_create", + "mts_update", + "amount", + "amount_orig", + "offer_type", + "_PLACEHOLDER", + "_PLACEHOLDER", + "flags", + "offer_status", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "rate", + "period", + "notify", + "hidden", + "_PLACEHOLDER", + "renew", + "_PLACEHOLDER" + ] +) -FundingCredit = generate_labeler_serializer("FundingCredit", klass=types.FundingCredit, labels=[ - "id", - "symbol", - "side", - "mts_create", - "mts_update", - "amount", - "flags", - "status", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "rate", - "period", - "mts_opening", - "mts_last_payout", - "notify", - "hidden", - "_PLACEHOLDER", - "renew", - "_PLACEHOLDER", - "no_close", - "position_pair" -]) +FundingCredit = generate_labeler_serializer( + name="FundingCredit", + klass=types.FundingCredit, + labels=[ + "id", + "symbol", + "side", + "mts_create", + "mts_update", + "amount", + "flags", + "status", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "rate", + "period", + "mts_opening", + "mts_last_payout", + "notify", + "hidden", + "_PLACEHOLDER", + "renew", + "_PLACEHOLDER", + "no_close", + "position_pair" + ] +) -FundingLoan = generate_labeler_serializer("FundingLoan", klass=types.FundingLoan, labels=[ - "id", - "symbol", - "side", - "mts_create", - "mts_update", - "amount", - "flags", - "status", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "rate", - "period", - "mts_opening", - "mts_last_payout", - "notify", - "hidden", - "_PLACEHOLDER", - "renew", - "_PLACEHOLDER", - "no_close" -]) +FundingLoan = generate_labeler_serializer( + name="FundingLoan", + klass=types.FundingLoan, + labels=[ + "id", + "symbol", + "side", + "mts_create", + "mts_update", + "amount", + "flags", + "status", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "rate", + "period", + "mts_opening", + "mts_last_payout", + "notify", + "hidden", + "_PLACEHOLDER", + "renew", + "_PLACEHOLDER", + "no_close" + ] +) -Wallet = generate_labeler_serializer("Wallet", klass=types.Wallet, labels=[ - "wallet_type", - "currency", - "balance", - "unsettled_interest", - "available_balance", - "last_change", - "trade_details" -]) +Wallet = generate_labeler_serializer( + name="Wallet", + klass=types.Wallet, + labels=[ + "wallet_type", + "currency", + "balance", + "unsettled_interest", + "available_balance", + "last_change", + "trade_details" + ] +) -Balance = generate_labeler_serializer("Balance", klass=types.Balance, labels=[ - "aum", - "aum_net", -]) +Balance = generate_labeler_serializer( + name="Balance", + klass=types.Balance, + labels=[ + "aum", + "aum_net" + ] +) #endregion