From deffce6deb20e98cefe7065287ba5e5f6388ee34 Mon Sep 17 00:00:00 2001 From: Lucas Date: Tue, 8 Aug 2023 18:00:25 +0800 Subject: [PATCH 01/29] Update adjusted_mid_price.py in func adjusted_mid_price maybe has a slip of pen? --- scripts/adjusted_mid_price.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/adjusted_mid_price.py b/scripts/adjusted_mid_price.py index 154f99501c..82e9830a1c 100644 --- a/scripts/adjusted_mid_price.py +++ b/scripts/adjusted_mid_price.py @@ -117,7 +117,7 @@ def adjusted_mid_price(self): ask_result = self.connector.get_quote_volume_for_base_amount(self.strategy["pair"], True, self.strategy["test_volume"]) bid_result = self.connector.get_quote_volume_for_base_amount(self.strategy["pair"], False, self.strategy["test_volume"]) average_ask = ask_result.result_volume / ask_result.query_volume - average_bid = bid_result = bid_result.result_volume / bid_result.query_volume + average_bid = bid_result.result_volume / bid_result.query_volume return average_bid + ((average_ask - average_bid) / 2) def format_status(self) -> str: From 61b35821e9b4c537841a54b9103470b9df978aaf Mon Sep 17 00:00:00 2001 From: nikspz <83953535+nikspz@users.noreply.github.com> Date: Fri, 25 Aug 2023 12:15:41 +0700 Subject: [PATCH 02/29] fix Update VERSION on staging --- hummingbot/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hummingbot/VERSION b/hummingbot/VERSION index dafcae148a..815d5ca06d 100644 --- a/hummingbot/VERSION +++ b/hummingbot/VERSION @@ -1 +1 @@ -dev-1.19.0 +1.19.0 From d8a233b042d4e6ab7c2d9c4bfac7fae3f67af739 Mon Sep 17 00:00:00 2001 From: nikspz <83953535+nikspz@users.noreply.github.com> Date: Fri, 25 Aug 2023 12:17:25 +0700 Subject: [PATCH 03/29] update-release-version-to-20230828 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5419d5ea4f..eaeb67fcd9 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ def build_extensions(self): def main(): cpu_count = os.cpu_count() or 8 - version = "20230724" + version = "20230828" packages = find_packages(include=["hummingbot", "hummingbot.*"]) package_data = { "hummingbot": [ From d4a32be671f459dbc9da89d6eac20ca74cf6aba6 Mon Sep 17 00:00:00 2001 From: dardonacci <36869960+cardosofede@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:40:01 +0200 Subject: [PATCH 04/29] (test) revert dependencies of pydantic --- setup/environment.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup/environment.yml b/setup/environment.yml index 8bc59cbe42..b8a9fb57ee 100644 --- a/setup/environment.yml +++ b/setup/environment.yml @@ -1,5 +1,6 @@ name: hummingbot channels: + - conda-forge - defaults dependencies: - bidict @@ -12,7 +13,7 @@ dependencies: - pandas=1.5.3 - pip=23.1.2 - prompt_toolkit=3.0.20 - - pydantic=1.9.* + - pydantic=1.9.2 - pytest - python=3.10.12 - pytables=3.8.0 From 2ea2633bf69d241e2bf967ac8487ec247e66d58e Mon Sep 17 00:00:00 2001 From: dardonacci <36869960+cardosofede@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:28:52 +0200 Subject: [PATCH 05/29] (test) improve environment.yml --- setup/environment.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup/environment.yml b/setup/environment.yml index b8a9fb57ee..b1d49c9794 100644 --- a/setup/environment.yml +++ b/setup/environment.yml @@ -1,6 +1,5 @@ name: hummingbot channels: - - conda-forge - defaults dependencies: - bidict @@ -38,7 +37,7 @@ dependencies: - commlib-py==0.10.6 - cryptography==3.4.7 - cython==3.0.0a10 - - diff-cover==5.1.2 + - diff-cover - docker==5.0.3 - eip712-structs==1.1.0 - ethsnarks-loopring==0.1.5 From 8e98cd1cee4329e6e32ae830a18ab91249f22f8a Mon Sep 17 00:00:00 2001 From: dardonacci <36869960+cardosofede@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:32:44 +0200 Subject: [PATCH 06/29] (feat) update pydantic --- setup/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/environment.yml b/setup/environment.yml index 1fe8cb0ee5..34c2c86e23 100644 --- a/setup/environment.yml +++ b/setup/environment.yml @@ -15,7 +15,7 @@ dependencies: - pandas=1.5.3 - pip=23.1.2 - prompt_toolkit=3.0.20 - - pydantic=1.9.2 + - pydantic=1.9.* - pytest==7.3.2 - python=3.10.12 - pytables=3.8.0 From 6bfb0a32465eb3485207cc9b155bad9da246a05f Mon Sep 17 00:00:00 2001 From: dardonacci <36869960+cardosofede@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:42:09 +0200 Subject: [PATCH 07/29] (feat) apply changes in env --- setup/environment.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/environment.yml b/setup/environment.yml index 34c2c86e23..cfa81bd282 100644 --- a/setup/environment.yml +++ b/setup/environment.yml @@ -1,7 +1,7 @@ name: hummingbot channels: - - conda-forge - defaults + - conda-forge dependencies: - aiounittest=1.4.1 - bidict @@ -40,7 +40,7 @@ dependencies: - commlib-py==0.10.6 - cryptography==3.4.7 - cython==3.0.0a10 - - diff-cover==5.1.2 + - diff-cover - docker==5.0.3 - dydx-v3-python==2.0.1 - ethsnarks-loopring==0.1.5 From bc0a6e36223a74f85e813c99ca964001a2544810 Mon Sep 17 00:00:00 2001 From: dardonacci <36869960+cardosofede@users.noreply.github.com> Date: Tue, 29 Aug 2023 16:14:59 +0200 Subject: [PATCH 08/29] (test) remove conda forge --- setup/environment.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/setup/environment.yml b/setup/environment.yml index cfa81bd282..2e8ebcb144 100644 --- a/setup/environment.yml +++ b/setup/environment.yml @@ -1,7 +1,6 @@ name: hummingbot channels: - defaults - - conda-forge dependencies: - aiounittest=1.4.1 - bidict From ab24db781f929e94a9296de8c4df33cf414eec8f Mon Sep 17 00:00:00 2001 From: drupman Date: Wed, 20 Sep 2023 20:54:10 -0300 Subject: [PATCH 09/29] (fix) replace deprecated endpoint and remove max_order_size --- hummingbot/connector/exchange/bitmart/bitmart_constants.py | 2 +- hummingbot/connector/exchange/bitmart/bitmart_exchange.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/hummingbot/connector/exchange/bitmart/bitmart_constants.py b/hummingbot/connector/exchange/bitmart/bitmart_constants.py index 5df3f5930d..476bada752 100644 --- a/hummingbot/connector/exchange/bitmart/bitmart_constants.py +++ b/hummingbot/connector/exchange/bitmart/bitmart_constants.py @@ -26,7 +26,7 @@ CREATE_ORDER_PATH_URL = "spot/v1/submit_order" CANCEL_ORDER_PATH_URL = "spot/v2/cancel_order" GET_ACCOUNT_SUMMARY_PATH_URL = "spot/v1/wallet" -GET_ORDER_DETAIL_PATH_URL = "spot/v1/order_detail" +GET_ORDER_DETAIL_PATH_URL = "spot/v2/order_detail" GET_TRADE_DETAIL_PATH_URL = "spot/v1/trades" SERVER_TIME_PATH = "system/time" diff --git a/hummingbot/connector/exchange/bitmart/bitmart_exchange.py b/hummingbot/connector/exchange/bitmart/bitmart_exchange.py index acf7301f45..243385aaf0 100644 --- a/hummingbot/connector/exchange/bitmart/bitmart_exchange.py +++ b/hummingbot/connector/exchange/bitmart/bitmart_exchange.py @@ -232,7 +232,6 @@ async def _format_trading_rules(self, symbols_details: Dict[str, Any]) -> List[T "quote_currency":"BTC", "quote_increment":"1.00000000", "base_min_size":"1.00000000", - "base_max_size":"10000000.00000000", "price_min_precision":6, "price_max_precision":8, "expiration":"NA", @@ -254,7 +253,6 @@ async def _format_trading_rules(self, symbols_details: Dict[str, Any]) -> List[T price_step = Decimal("1") / Decimal(str(math.pow(10, price_decimals))) result.append(TradingRule(trading_pair=trading_pair, min_order_size=Decimal(str(rule["base_min_size"])), - max_order_size=Decimal(str(rule["base_max_size"])), min_order_value=Decimal(str(rule["min_buy_amount"])), min_base_amount_increment=Decimal(str(rule["base_min_size"])), min_price_increment=price_step)) @@ -291,7 +289,7 @@ async def _update_balances(self): async def _request_order_update(self, order: InFlightOrder) -> Dict[str, Any]: return await self._api_get( path_url=CONSTANTS.GET_ORDER_DETAIL_PATH_URL, - params={"clientOrderId": order.client_order_id}, + params={"order_id": order.exchange_order_id}, is_auth_required=True) async def _request_order_fills(self, order: InFlightOrder) -> Dict[str, Any]: From 25351d9cd1ec187284635a91a9693d57f56ca213 Mon Sep 17 00:00:00 2001 From: drupman Date: Wed, 20 Sep 2023 21:43:51 -0300 Subject: [PATCH 10/29] (fix) remove base_max_size from tests --- .../connector/exchange/bitmart/test_bitmart_exchange.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/hummingbot/connector/exchange/bitmart/test_bitmart_exchange.py b/test/hummingbot/connector/exchange/bitmart/test_bitmart_exchange.py index bde60b0bb0..d9f4becb44 100644 --- a/test/hummingbot/connector/exchange/bitmart/test_bitmart_exchange.py +++ b/test/hummingbot/connector/exchange/bitmart/test_bitmart_exchange.py @@ -65,7 +65,6 @@ def all_symbols_request_mock_response(self): "quote_currency": self.quote_asset, "quote_increment": "1.00000000", "base_min_size": "1.00000000", - "base_max_size": "10000000.00000000", "price_min_precision": 6, "price_max_precision": 8, "expiration": "NA", @@ -120,7 +119,6 @@ def all_symbols_including_invalid_pair_mock_response(self) -> Tuple[str, Any]: "quote_currency": self.quote_asset, "quote_increment": "1.00000000", "base_min_size": "1.00000000", - "base_max_size": "10000000.00000000", "price_min_precision": 6, "price_max_precision": 8, "expiration": "NA", @@ -135,7 +133,6 @@ def all_symbols_including_invalid_pair_mock_response(self) -> Tuple[str, Any]: "quote_currency": "PAIR", "quote_increment": "1.00000000", "base_min_size": "1.00000000", - "base_max_size": "10000000.00000000", "price_min_precision": 6, "price_max_precision": 8, "expiration": "NA", @@ -190,7 +187,6 @@ def trading_rules_request_mock_response(self): "quote_currency": self.quote_asset, "quote_increment": "1.00000000", "base_min_size": "5.00000000", - "base_max_size": "10000000.00000000", "price_min_precision": 6, "price_max_precision": 8, "expiration": "NA", @@ -296,7 +292,6 @@ def expected_trading_rule(self): return TradingRule( trading_pair=self.trading_pair, min_order_size=Decimal(self.trading_rules_request_mock_response["data"]["symbols"][0]["base_min_size"]), - max_order_size=Decimal(self.trading_rules_request_mock_response["data"]["symbols"][0]["base_max_size"]), min_order_value=Decimal(self.trading_rules_request_mock_response["data"]["symbols"][0]["min_buy_amount"]), min_base_amount_increment=Decimal(str( self.trading_rules_request_mock_response["data"]["symbols"][0]["base_min_size"])), From 8a47fc42bb1accd08ac0e5125622618e06865431 Mon Sep 17 00:00:00 2001 From: drupman Date: Wed, 20 Sep 2023 22:08:08 -0300 Subject: [PATCH 11/29] (fix) adapt tests --- .../connector/exchange/bitmart/test_bitmart_exchange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hummingbot/connector/exchange/bitmart/test_bitmart_exchange.py b/test/hummingbot/connector/exchange/bitmart/test_bitmart_exchange.py index d9f4becb44..0c251a68f7 100644 --- a/test/hummingbot/connector/exchange/bitmart/test_bitmart_exchange.py +++ b/test/hummingbot/connector/exchange/bitmart/test_bitmart_exchange.py @@ -370,7 +370,7 @@ def validate_order_cancelation_request(self, order: InFlightOrder, request_call: def validate_order_status_request(self, order: InFlightOrder, request_call: RequestCall): request_params = request_call.kwargs["params"] - self.assertEqual(order.client_order_id, request_params["clientOrderId"]) + self.assertEqual(order.exchange_order_id, request_params["order_id"]) def validate_trades_request(self, order: InFlightOrder, request_call: RequestCall): request_params = request_call.kwargs["params"] From bd87a36ba9c4cdeb02f4887ac2224953eb6db1e3 Mon Sep 17 00:00:00 2001 From: bczhang Date: Fri, 22 Sep 2023 13:32:12 +0800 Subject: [PATCH 12/29] fix bug --- .../derivative/kucoin_perpetual/kucoin_perpetual_derivative.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py index 59fdbec483..14504ed0af 100644 --- a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py +++ b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py @@ -615,7 +615,7 @@ async def _process_account_position_event(self, position_msg: Dict[str, Any]): if "changeReason" in position_msg and position_msg["changeReason"] != "markPriceChange": ex_trading_pair = position_msg["symbol"] trading_pair = await self.trading_pair_associated_to_exchange_symbol(symbol=ex_trading_pair) - amount = Decimal(str(position_msg["currentQty"])) + amount = self.get_value_of_contracts(trading_pair, int(str(position_msg["currentQty"]))) position_side = PositionSide.SHORT if amount < 0 else PositionSide.LONG entry_price = Decimal(str(position_msg["avgEntryPrice"])) leverage = Decimal(str(position_msg["realLeverage"])) From d5e0155ec23f5986a631808bcf681acd5f9009c5 Mon Sep 17 00:00:00 2001 From: bczhang Date: Fri, 22 Sep 2023 18:24:48 +0800 Subject: [PATCH 13/29] format code --- .../kucoin_perpetual/kucoin_perpetual_derivative.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py index 14504ed0af..d742b45638 100644 --- a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py +++ b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py @@ -419,7 +419,7 @@ async def _update_balances(self): self._account_balances.clear() if wallet_balance["data"] is not None: - if type(wallet_balance["data"]) == list: + if type(wallet_balance["data"]) is list: for balance_data in wallet_balance["data"]: currency = str(balance_data["currency"]) self._account_balances[currency] = Decimal(str(balance_data["marginBalance"])) @@ -591,7 +591,7 @@ async def _user_stream_event_listener(self): self._order_tracker.process_order_update(order_update=order_update) elif endpoint == CONSTANTS.WS_SUBSCRIPTION_WALLET_ENDPOINT_NAME: - if type(payload) == list: + if type(payload) is list: for wallet_msg in payload: self._process_wallet_event_message(wallet_msg) else: @@ -831,7 +831,7 @@ async def _get_last_traded_price(self, trading_pair: str) -> float: limit_id=CONSTANTS.LATEST_SYMBOL_INFORMATION_ENDPOINT, ) - if type(resp_json["data"]) == list: + if type(resp_json["data"]) is list: if "lastTradePrice" in resp_json["data"][0]: price = float(resp_json["data"][0]["lastTradePrice"]) else: From b9e8acb6802f2e9b6d347f51b713e203e4d5373a Mon Sep 17 00:00:00 2001 From: bczhang Date: Fri, 22 Sep 2023 18:26:50 +0800 Subject: [PATCH 14/29] format code --- .../kucoin_perpetual/kucoin_perpetual_derivative.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py index d742b45638..3b4d213f62 100644 --- a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py +++ b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py @@ -419,7 +419,7 @@ async def _update_balances(self): self._account_balances.clear() if wallet_balance["data"] is not None: - if type(wallet_balance["data"]) is list: + if isinstance(wallet_balance["data"],list): for balance_data in wallet_balance["data"]: currency = str(balance_data["currency"]) self._account_balances[currency] = Decimal(str(balance_data["marginBalance"])) @@ -591,7 +591,7 @@ async def _user_stream_event_listener(self): self._order_tracker.process_order_update(order_update=order_update) elif endpoint == CONSTANTS.WS_SUBSCRIPTION_WALLET_ENDPOINT_NAME: - if type(payload) is list: + if isinstance(payload, list): for wallet_msg in payload: self._process_wallet_event_message(wallet_msg) else: @@ -830,8 +830,7 @@ async def _get_last_traded_price(self, trading_pair: str) -> float: path_url=CONSTANTS.LATEST_SYMBOL_INFORMATION_ENDPOINT.format(symbol=exchange_symbol), limit_id=CONSTANTS.LATEST_SYMBOL_INFORMATION_ENDPOINT, ) - - if type(resp_json["data"]) is list: + if isinstance(resp_json["data"], list): if "lastTradePrice" in resp_json["data"][0]: price = float(resp_json["data"][0]["lastTradePrice"]) else: From 5409fa0c043585e9f401a303464aa21ca1b0e675 Mon Sep 17 00:00:00 2001 From: bczhang Date: Fri, 22 Sep 2023 18:41:49 +0800 Subject: [PATCH 15/29] format code --- .../derivative/kucoin_perpetual/kucoin_perpetual_derivative.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py index 3b4d213f62..d6bdda7a91 100644 --- a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py +++ b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py @@ -419,7 +419,7 @@ async def _update_balances(self): self._account_balances.clear() if wallet_balance["data"] is not None: - if isinstance(wallet_balance["data"],list): + if isinstance(wallet_balance["data"], list): for balance_data in wallet_balance["data"]: currency = str(balance_data["currency"]) self._account_balances[currency] = Decimal(str(balance_data["marginBalance"])) From 50eb6236731b9c62c79903b2d56a39ffa37aebe1 Mon Sep 17 00:00:00 2001 From: bczhang Date: Mon, 25 Sep 2023 11:29:05 +0800 Subject: [PATCH 16/29] update --- .../kucoin_perpetual/kucoin_perpetual_derivative.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py index d6bdda7a91..d3bbf5b8d8 100644 --- a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py +++ b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py @@ -456,7 +456,7 @@ async def _update_positions(self): data = position ex_trading_pair = data.get("symbol") hb_trading_pair = await self.trading_pair_associated_to_exchange_symbol(ex_trading_pair) - amount = self.get_value_of_contracts(hb_trading_pair, int(str(data["currentQty"]))) + amount = self.get_value_of_contracts(hb_trading_pair, int(Decimal(data["currentQty"]))) position_side = PositionSide.SHORT if amount < 0 else PositionSide.LONG unrealized_pnl = Decimal(str(data["unrealisedPnl"])) entry_price = Decimal(str(data["avgEntryPrice"])) @@ -615,7 +615,7 @@ async def _process_account_position_event(self, position_msg: Dict[str, Any]): if "changeReason" in position_msg and position_msg["changeReason"] != "markPriceChange": ex_trading_pair = position_msg["symbol"] trading_pair = await self.trading_pair_associated_to_exchange_symbol(symbol=ex_trading_pair) - amount = self.get_value_of_contracts(trading_pair, int(str(position_msg["currentQty"]))) + amount = self.get_value_of_contracts(trading_pair, int(Decimal(position_msg["currentQty"]))) position_side = PositionSide.SHORT if amount < 0 else PositionSide.LONG entry_price = Decimal(str(position_msg["avgEntryPrice"])) leverage = Decimal(str(position_msg["realLeverage"])) From 5aef16ea3d00b94af46855e6c8e233470547153d Mon Sep 17 00:00:00 2001 From: bczhang Date: Mon, 25 Sep 2023 11:51:20 +0800 Subject: [PATCH 17/29] update --- .../kucoin_perpetual/kucoin_perpetual_derivative.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py index d3bbf5b8d8..c473af4165 100644 --- a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py +++ b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_derivative.py @@ -456,7 +456,7 @@ async def _update_positions(self): data = position ex_trading_pair = data.get("symbol") hb_trading_pair = await self.trading_pair_associated_to_exchange_symbol(ex_trading_pair) - amount = self.get_value_of_contracts(hb_trading_pair, int(Decimal(data["currentQty"]))) + amount = self.get_value_of_contracts(hb_trading_pair, int(data["currentQty"])) position_side = PositionSide.SHORT if amount < 0 else PositionSide.LONG unrealized_pnl = Decimal(str(data["unrealisedPnl"])) entry_price = Decimal(str(data["avgEntryPrice"])) @@ -615,7 +615,7 @@ async def _process_account_position_event(self, position_msg: Dict[str, Any]): if "changeReason" in position_msg and position_msg["changeReason"] != "markPriceChange": ex_trading_pair = position_msg["symbol"] trading_pair = await self.trading_pair_associated_to_exchange_symbol(symbol=ex_trading_pair) - amount = self.get_value_of_contracts(trading_pair, int(Decimal(position_msg["currentQty"]))) + amount = self.get_value_of_contracts(trading_pair, int(position_msg["currentQty"])) position_side = PositionSide.SHORT if amount < 0 else PositionSide.LONG entry_price = Decimal(str(position_msg["avgEntryPrice"])) leverage = Decimal(str(position_msg["realLeverage"])) From ed52ac1fd61082cd6707f6fbb95980bca3509157 Mon Sep 17 00:00:00 2001 From: bczhang Date: Mon, 25 Sep 2023 12:39:32 +0800 Subject: [PATCH 18/29] update --- .../kucoin_perpetual/test_kucoin_perpetual_derivative.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py index d13f6a63f6..a2d3aeea2c 100644 --- a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py +++ b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py @@ -1018,7 +1018,7 @@ def position_event_for_full_fill_websocket_update(self, order: InFlightOrder, un "changeReason": "positionChange", "currentCost": str(position_value), "openingTimestamp": 1558433191000, - "currentQty": -float(order.amount), + "currentQty": -int(order.amount), "delevPercentage": 0.52, "currentComm": 0.00000271, "realisedGrossCost": 0E-8, From 30ec16b8767fc9e3fbcc044a84f156a8c1a4a3c6 Mon Sep 17 00:00:00 2001 From: bczhang Date: Mon, 25 Sep 2023 13:30:31 +0800 Subject: [PATCH 19/29] update unittest --- .../test_kucoin_perpetual_derivative.py | 94 ++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py index a2d3aeea2c..233a3e6eb0 100644 --- a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py +++ b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py @@ -15,10 +15,11 @@ from hummingbot.client.config.client_config_map import ClientConfigMap from hummingbot.client.config.config_helpers import ClientConfigAdapter from hummingbot.connector.derivative.kucoin_perpetual.kucoin_perpetual_derivative import KucoinPerpetualDerivative +from hummingbot.connector.derivative.position import Position from hummingbot.connector.test_support.perpetual_derivative_test import AbstractPerpetualDerivativeTests from hummingbot.connector.trading_rule import TradingRule from hummingbot.connector.utils import combine_to_hb_trading_pair -from hummingbot.core.data_type.common import OrderType, PositionAction, PositionMode, TradeType +from hummingbot.core.data_type.common import OrderType, PositionAction, PositionMode, TradeType, PositionSide from hummingbot.core.data_type.funding_info import FundingInfo from hummingbot.core.data_type.in_flight_order import InFlightOrder from hummingbot.core.data_type.trade_fee import AddedToCostTradeFee, TokenAmount, TradeFeeBase @@ -1555,3 +1556,94 @@ def test_start_network_update_trading_rules(self, mock_api): self.assertEqual(1, len(self.exchange.trading_rules)) self.assertIn(self.trading_pair, self.exchange.trading_rules) self.assertEqual(repr(self.expected_trading_rule), repr(self.exchange.trading_rules[self.trading_pair])) + + @aioresponses() + def test_user_stream_update_for_order_full_fill(self, mock_api): + self.exchange._set_current_timestamp(1640780000) + leverage = 2 + self.exchange._perpetual_trading.set_leverage(self.trading_pair, leverage) + self.exchange.start_tracking_order( + order_id=self.client_order_id_prefix + "1", + exchange_order_id=self.exchange_order_id_prefix + "1", + trading_pair=self.trading_pair, + order_type=OrderType.LIMIT, + trade_type=TradeType.SELL, + price=Decimal("10000"), + amount=Decimal("1"), + position_action=PositionAction.OPEN, + ) + order = self.exchange.in_flight_orders[self.client_order_id_prefix + "1"] + + order_event = self.order_event_for_full_fill_websocket_update(order=order) + trade_event = self.trade_event_for_full_fill_websocket_update(order=order) + expected_unrealized_pnl = 12 + position_event = self.position_event_for_full_fill_websocket_update( + order=order, unrealized_pnl=expected_unrealized_pnl + ) + + mock_queue = AsyncMock() + event_messages = [] + if trade_event: + event_messages.append(trade_event) + if order_event: + event_messages.append(order_event) + if position_event: + event_messages.append(position_event) + event_messages.append(asyncio.CancelledError) + mock_queue.get.side_effect = event_messages + self.exchange._user_stream_tracker._user_stream = mock_queue + + if self.is_order_fill_http_update_executed_during_websocket_order_event_processing: + self.configure_full_fill_trade_response( + order=order, + mock_api=mock_api) + + try: + self.async_run_with_timeout(self.exchange._user_stream_event_listener()) + except asyncio.CancelledError: + pass + # Execute one more synchronization to ensure the async task that processes the update is finished + self.async_run_with_timeout(order.wait_until_completely_filled()) + + fill_event = self.order_filled_logger.event_log[0] + self.assertEqual(self.exchange.current_timestamp, fill_event.timestamp) + self.assertEqual(order.client_order_id, fill_event.order_id) + self.assertEqual(order.trading_pair, fill_event.trading_pair) + self.assertEqual(order.trade_type, fill_event.trade_type) + self.assertEqual(order.order_type, fill_event.order_type) + self.assertEqual(order.price, fill_event.price) + self.assertEqual(order.amount, fill_event.amount) + expected_fee = self.expected_fill_fee + self.assertEqual(expected_fee, fill_event.trade_fee) + self.assertEqual(leverage, fill_event.leverage) + self.assertEqual(PositionAction.OPEN.value, fill_event.position) + + sell_event = self.sell_order_completed_logger.event_log[0] + self.assertEqual(self.exchange.current_timestamp, sell_event.timestamp) + self.assertEqual(order.client_order_id, sell_event.order_id) + self.assertEqual(order.base_asset, sell_event.base_asset) + self.assertEqual(order.quote_asset, sell_event.quote_asset) + self.assertEqual(order.amount, sell_event.base_asset_amount) + self.assertEqual(order.amount * fill_event.price, sell_event.quote_asset_amount) + self.assertEqual(order.order_type, sell_event.order_type) + self.assertEqual(order.exchange_order_id, sell_event.exchange_order_id) + self.assertNotIn(order.client_order_id, self.exchange.in_flight_orders) + self.assertTrue(order.is_filled) + self.assertTrue(order.is_done) + + self.assertTrue( + self.is_logged( + "INFO", + f"SELL order {order.client_order_id} completely filled." + ) + ) + + self.assertEqual(1, len(self.exchange.account_positions)) + + position: Position = self.exchange.account_positions[self.trading_pair] + self.assertEqual(self.trading_pair, position.trading_pair) + self.assertEqual(PositionSide.SHORT, position.position_side) + self.assertEqual(expected_unrealized_pnl, position.unrealized_pnl) + self.assertEqual(fill_event.price, position.entry_price) + self.assertEqual(-fill_event.amount, (self.exchange.get_quantity_of_contracts(self.trading_pair, position.amount))) + self.assertEqual(leverage, position.leverage) \ No newline at end of file From 7ae6bf47262edd3debfa2470851bd0fa65d5f94c Mon Sep 17 00:00:00 2001 From: bczhang Date: Mon, 25 Sep 2023 14:42:18 +0800 Subject: [PATCH 20/29] format --- .../kucoin_perpetual/test_kucoin_perpetual_derivative.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py index 233a3e6eb0..5cc7bae053 100644 --- a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py +++ b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py @@ -1646,4 +1646,4 @@ def test_user_stream_update_for_order_full_fill(self, mock_api): self.assertEqual(expected_unrealized_pnl, position.unrealized_pnl) self.assertEqual(fill_event.price, position.entry_price) self.assertEqual(-fill_event.amount, (self.exchange.get_quantity_of_contracts(self.trading_pair, position.amount))) - self.assertEqual(leverage, position.leverage) \ No newline at end of file + self.assertEqual(leverage, position.leverage) From 8ebaf6f4052a07cff5163d2fe2ef95608e2ebf1d Mon Sep 17 00:00:00 2001 From: bczhang Date: Mon, 25 Sep 2023 16:47:13 +0800 Subject: [PATCH 21/29] format --- .../kucoin_perpetual/test_kucoin_perpetual_derivative.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py index 5cc7bae053..c16a365326 100644 --- a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py +++ b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py @@ -19,7 +19,7 @@ from hummingbot.connector.test_support.perpetual_derivative_test import AbstractPerpetualDerivativeTests from hummingbot.connector.trading_rule import TradingRule from hummingbot.connector.utils import combine_to_hb_trading_pair -from hummingbot.core.data_type.common import OrderType, PositionAction, PositionMode, TradeType, PositionSide +from hummingbot.core.data_type.common import OrderType, PositionAction, PositionMode, PositionSide, TradeType from hummingbot.core.data_type.funding_info import FundingInfo from hummingbot.core.data_type.in_flight_order import InFlightOrder from hummingbot.core.data_type.trade_fee import AddedToCostTradeFee, TokenAmount, TradeFeeBase From 869fee6cd48ee58c55c3511ef590f4ccccb4638f Mon Sep 17 00:00:00 2001 From: bczhang Date: Mon, 25 Sep 2023 17:34:49 +0800 Subject: [PATCH 22/29] format --- .../kucoin_perpetual/test_kucoin_perpetual_derivative.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py index c16a365326..1dfe01fc07 100644 --- a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py +++ b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py @@ -1560,6 +1560,7 @@ def test_start_network_update_trading_rules(self, mock_api): @aioresponses() def test_user_stream_update_for_order_full_fill(self, mock_api): self.exchange._set_current_timestamp(1640780000) + self._simulate_trading_rules_initialized() leverage = 2 self.exchange._perpetual_trading.set_leverage(self.trading_pair, leverage) self.exchange.start_tracking_order( From 1bb2d1b60d075bd15f361d1dd575dd5c10c3d6cb Mon Sep 17 00:00:00 2001 From: bczhang Date: Tue, 26 Sep 2023 11:33:53 +0800 Subject: [PATCH 23/29] update unittest --- .../test_kucoin_perpetual_derivative.py | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py index 1dfe01fc07..eeacd4c940 100644 --- a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py +++ b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_derivative.py @@ -975,7 +975,7 @@ def trade_event_for_full_fill_websocket_update(self, order: InFlightOrder): "size": float(order.amount) * 1000, "fee": str(self.expected_fill_fee.percent), "remainSize": "0", - "matchSize": float(order.amount) * 1000, + "matchSize": float(order.amount) * 1000000, "canceledSize": "0", "clientOid": order.client_order_id or "", "orderTime": 1545914149935808589, @@ -1648,3 +1648,66 @@ def test_user_stream_update_for_order_full_fill(self, mock_api): self.assertEqual(fill_event.price, position.entry_price) self.assertEqual(-fill_event.amount, (self.exchange.get_quantity_of_contracts(self.trading_pair, position.amount))) self.assertEqual(leverage, position.leverage) + + @aioresponses() + def test_lost_order_user_stream_full_fill_events_are_processed(self, mock_api): + self.exchange._set_current_timestamp(1640780000) + self._simulate_trading_rules_initialized() + self.exchange.start_tracking_order( + order_id=self.client_order_id_prefix + "1", + exchange_order_id=str(self.expected_exchange_order_id), + trading_pair=self.trading_pair, + order_type=OrderType.LIMIT, + trade_type=TradeType.BUY, + price=Decimal("10000"), + amount=Decimal("1"), + ) + order = self.exchange.in_flight_orders[self.client_order_id_prefix + "1"] + + for _ in range(self.exchange._order_tracker._lost_order_count_limit + 1): + self.async_run_with_timeout( + self.exchange._order_tracker.process_order_not_found(client_order_id=order.client_order_id)) + + self.assertNotIn(order.client_order_id, self.exchange.in_flight_orders) + + order_event = self.order_event_for_full_fill_websocket_update(order=order) + trade_event = self.trade_event_for_full_fill_websocket_update(order=order) + + mock_queue = AsyncMock() + event_messages = [] + if trade_event: + event_messages.append(trade_event) + if order_event: + event_messages.append(order_event) + event_messages.append(asyncio.CancelledError) + mock_queue.get.side_effect = event_messages + self.exchange._user_stream_tracker._user_stream = mock_queue + + if self.is_order_fill_http_update_executed_during_websocket_order_event_processing: + self.configure_full_fill_trade_response( + order=order, + mock_api=mock_api) + + try: + self.async_run_with_timeout(self.exchange._user_stream_event_listener()) + except asyncio.CancelledError: + pass + # Execute one more synchronization to ensure the async task that processes the update is finished + self.async_run_with_timeout(order.wait_until_completely_filled()) + + fill_event = self.order_filled_logger.event_log[0] + self.assertEqual(self.exchange.current_timestamp, fill_event.timestamp) + self.assertEqual(order.client_order_id, fill_event.order_id) + self.assertEqual(order.trading_pair, fill_event.trading_pair) + self.assertEqual(order.trade_type, fill_event.trade_type) + self.assertEqual(order.order_type, fill_event.order_type) + self.assertEqual(order.price, fill_event.price) + self.assertEqual(order.amount, fill_event.amount) + expected_fee = self.expected_fill_fee + self.assertEqual(expected_fee, fill_event.trade_fee) + + self.assertEqual(0, len(self.buy_order_completed_logger.event_log)) + self.assertNotIn(order.client_order_id, self.exchange.in_flight_orders) + self.assertNotIn(order.client_order_id, self.exchange._order_tracker.lost_orders) + self.assertTrue(order.is_filled) + self.assertTrue(order.is_failure) From 0d646b7db92ae70c3d7bbd3c8cfc0f77d765636c Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 27 Sep 2023 10:26:21 -0300 Subject: [PATCH 24/29] (feat) remove kucoin testnet from connector status --- hummingbot/connector/connector_status.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hummingbot/connector/connector_status.py b/hummingbot/connector/connector_status.py index 0e6ebd5279..a2e4b26742 100644 --- a/hummingbot/connector/connector_status.py +++ b/hummingbot/connector/connector_status.py @@ -51,7 +51,6 @@ 'xswap': 'bronze', 'dexalot': 'silver', 'kucoin_perpetual': 'silver', - 'kucoin_perpetual_testnet': 'silver', 'injective_perpetual': 'bronze', 'bit_com_perpetual': 'bronze', 'bit_com_perpetual_testnet': 'bronze', From e8544ed5c59a9a82345f0363c4e5a41e3dd2daf9 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 27 Sep 2023 10:26:29 -0300 Subject: [PATCH 25/29] (feat) remove endpoints of testnet --- .../kucoin_perpetual/kucoin_perpetual_constants.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_constants.py b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_constants.py index 625d37fe8e..3a1770f499 100644 --- a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_constants.py +++ b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_constants.py @@ -10,13 +10,9 @@ DEFAULT_TIME_IN_FORCE = "GTC" -REST_URLS = {"kucoin_perpetual_main": "https://api-futures.kucoin.com/", - "kucoin_perpetual_testnet": "https://api-sandbox-futures.kucoin.com/"} -WSS_PUBLIC_URLS = {"kucoin_perpetual_main": "wss://stream.kucoin.com/realtime_public", - "kucoin_perpetual_testnet": "wss://stream-testnet.kucoin.com/realtime_public"} -WSS_PRIVATE_URLS = {"kucoin_perpetual_main": "wss://stream.kucoin.com/realtime_private", - "kucoin_perpetual_testnet": "wss://stream-testnet.kucoin.com/realtime_private"} - +REST_URLS = {"kucoin_perpetual_main": "https://api-futures.kucoin.com/"} +WSS_PUBLIC_URLS = {"kucoin_perpetual_main": "wss://stream.kucoin.com/realtime_public"} +WSS_PRIVATE_URLS = {"kucoin_perpetual_main": "wss://stream.kucoin.com/realtime_private"} REST_API_VERSION = "api/v1" HB_PARTNER_ID = "Hummingbot" From 03b8dfd7aaa3a99ad54749c1e1a3f225320309d8 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 27 Sep 2023 10:26:46 -0300 Subject: [PATCH 26/29] (feat) remove kucoin config map for testnet --- .../kucoin_perpetual_utils.py | 49 ------------------- 1 file changed, 49 deletions(-) diff --git a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_utils.py b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_utils.py index 3e8460a4ec..b907dbe204 100644 --- a/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_utils.py +++ b/hummingbot/connector/derivative/kucoin_perpetual/kucoin_perpetual_utils.py @@ -65,52 +65,3 @@ class Config: KEYS = KucoinPerpetualConfigMap.construct() - -OTHER_DOMAINS = ["kucoin_perpetual_testnet"] -OTHER_DOMAINS_PARAMETER = {"kucoin_perpetual_testnet": "kucoin_perpetual_testnet"} -OTHER_DOMAINS_EXAMPLE_PAIR = {"kucoin_perpetual_testnet": "BTC-USDT"} -OTHER_DOMAINS_DEFAULT_FEES = { - "kucoin_perpetual_testnet": TradeFeeSchema( - maker_percent_fee_decimal=Decimal("-0.00025"), - taker_percent_fee_decimal=Decimal("0.00075"), - ) -} - - -class KucoinPerpetualTestnetConfigMap(BaseConnectorConfigMap): - connector: str = Field(default="kucoin_perpetual_testnet", client_data=None) - kucoin_perpetual_testnet_api_key: SecretStr = Field( - default=..., - client_data=ClientFieldData( - prompt=lambda cm: "Enter your Kucoin Perpetual Testnet API key", - is_secure=True, - is_connect_key=True, - prompt_on_new=True, - ) - ) - kucoin_perpetual_testnet_secret_key: SecretStr = Field( - default=..., - client_data=ClientFieldData( - prompt=lambda cm: "Enter your Kucoin Perpetual Testnet secret key", - is_secure=True, - is_connect_key=True, - prompt_on_new=True, - ) - ) - kucoin_perpetual_testnet_passphrase: SecretStr = Field( - default=..., - client_data=ClientFieldData( - prompt=lambda cm: "Enter your KuCoin Perpetual Testnet passphrase", - is_secure=True, - is_connect_key=True, - prompt_on_new=True, - ) - ) - - class Config: - title = "kucoin_perpetual_testnet" - - -OTHER_DOMAINS_KEYS = { - "kucoin_perpetual_testnet": KucoinPerpetualTestnetConfigMap.construct() -} From 1f75a85e93d460f087c72577dbc1e749358fa10d Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 27 Sep 2023 10:26:57 -0300 Subject: [PATCH 27/29] (feat) remove test that were using testnet --- .../kucoin_perpetual/test_kucoin_perpetual_web_utils.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_web_utils.py b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_web_utils.py index 0c3c0c4dde..622a48ca6b 100644 --- a/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_web_utils.py +++ b/test/hummingbot/connector/derivative/kucoin_perpetual/test_kucoin_perpetual_web_utils.py @@ -9,6 +9,3 @@ def test_get_rest_url_for_endpoint(self): url = web_utils.get_rest_url_for_endpoint(endpoint, domain="kucoin_perpetual_main") self.assertEqual("https://api-futures.kucoin.com/testEndpoint", url) - - url = web_utils.get_rest_url_for_endpoint(endpoint, domain="kucoin_perpetual_testnet") - self.assertEqual("https://api-sandbox-futures.kucoin.com/testEndpoint", url) From f25311b4b4ef239b5fb2b9432540e354a12c417c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferit=20Tun=C3=A7er?= Date: Fri, 29 Sep 2023 02:35:38 +0100 Subject: [PATCH 28/29] (fix) fixes #6593 docker configuration max-file by converting the value to a string --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 32f66ecf43..ac82395c0c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,7 @@ services: driver: "json-file" options: max-size: "10m" - max-file: 5 + max-file: "5" tty: true stdin_open: true network_mode: host From 8cacc0069aa65b0264de95a1b74da89ac25eef59 Mon Sep 17 00:00:00 2001 From: nikspz <83953535+nikspz@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:15:41 +0800 Subject: [PATCH 29/29] fix/Update development VERSION to dev-1.21.0 --- hummingbot/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hummingbot/VERSION b/hummingbot/VERSION index 55383ee68c..453812a7ba 100644 --- a/hummingbot/VERSION +++ b/hummingbot/VERSION @@ -1 +1 @@ -dev-1.20.0 +dev-1.21.0