From 51ba4d14e945dc84ab265383d6d4799bf5eb10e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 03:56:46 +0000 Subject: [PATCH 01/48] Bump pydantic from 1.10.7 to 1.10.8 Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.7 to 1.10.8. - [Release notes](https://github.com/pydantic/pydantic/releases) - [Changelog](https://github.com/pydantic/pydantic/blob/v1.10.8/HISTORY.md) - [Commits](https://github.com/pydantic/pydantic/compare/v1.10.7...v1.10.8) --- updated-dependencies: - dependency-name: pydantic dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index cff54ca1c..e8ba3238d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,7 +39,7 @@ sdnotify==0.3.2 # API Server fastapi==0.95.2 -pydantic==1.10.7 +pydantic==1.10.8 uvicorn==0.22.0 pyjwt==2.7.0 aiofiles==23.1.0 From 12af6ea766a7b34a31a07d267787ae83f371bcdf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 03:56:50 +0000 Subject: [PATCH 02/48] Bump pytest-cov from 4.0.0 to 4.1.0 Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 4.0.0 to 4.1.0. - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.0.0...v4.1.0) --- updated-dependencies: - dependency-name: pytest-cov dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index cc3463174..5423d35be 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -12,7 +12,7 @@ mypy==1.3.0 pre-commit==3.3.2 pytest==7.3.1 pytest-asyncio==0.21.0 -pytest-cov==4.0.0 +pytest-cov==4.1.0 pytest-mock==3.10.0 pytest-random-order==1.1.0 isort==5.12.0 From 3bc390cb2e9c6a736c36e7f0d38f4a0376cb8120 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 03:56:53 +0000 Subject: [PATCH 03/48] Bump types-requests from 2.30.0.0 to 2.31.0.0 Bumps [types-requests](https://github.com/python/typeshed) from 2.30.0.0 to 2.31.0.0. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index cc3463174..d5b7ca577 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -25,6 +25,6 @@ nbconvert==7.4.0 # mypy types types-cachetools==5.3.0.5 types-filelock==3.2.7 -types-requests==2.30.0.0 +types-requests==2.31.0.0 types-tabulate==0.9.0.2 types-python-dateutil==2.8.19.13 From 4e9a43ebf602b57cb9cead2bda2a348e4e759313 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 03:56:56 +0000 Subject: [PATCH 04/48] Bump cachetools from 5.3.0 to 5.3.1 Bumps [cachetools](https://github.com/tkem/cachetools) from 5.3.0 to 5.3.1. - [Changelog](https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tkem/cachetools/compare/v5.3.0...v5.3.1) --- updated-dependencies: - dependency-name: cachetools dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index cff54ca1c..b12e2d859 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ python-telegram-bot==20.3 # can't be hard-pinned due to telegram-bot pinning httpx with ~ httpx>=0.23.3 arrow==1.2.3 -cachetools==5.3.0 +cachetools==5.3.1 requests==2.31.0 urllib3==2.0.2 jsonschema==4.17.3 From 8fdec5f3a6e17faf28fc980f6a94b30c0ad75127 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 03:57:05 +0000 Subject: [PATCH 05/48] Bump ccxt from 3.1.5 to 3.1.13 Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.1.5 to 3.1.13. - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/3.1.5...3.1.13) --- updated-dependencies: - dependency-name: ccxt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index cff54ca1c..a0e6c0387 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.24.3 pandas==2.0.1 pandas-ta==0.3.14b -ccxt==3.1.5 +ccxt==3.1.13 cryptography==40.0.2; platform_machine != 'armv7l' cryptography==40.0.1; platform_machine == 'armv7l' aiohttp==3.8.4 From 90808683e2c33ec86bcc374c8b7804e21dbcd009 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 03:57:13 +0000 Subject: [PATCH 06/48] Bump ruff from 0.0.269 to 0.0.270 Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.269 to 0.0.270. - [Release notes](https://github.com/charliermarsh/ruff/releases) - [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md) - [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.269...v0.0.270) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index cc3463174..1a68daa54 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -7,7 +7,7 @@ -r docs/requirements-docs.txt coveralls==3.3.1 -ruff==0.0.269 +ruff==0.0.270 mypy==1.3.0 pre-commit==3.3.2 pytest==7.3.1 From cb7a0f9bff3d4825cca56a589f12399f5d7a686d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 03:57:23 +0000 Subject: [PATCH 07/48] Bump orjson from 3.8.12 to 3.8.14 Bumps [orjson](https://github.com/ijl/orjson) from 3.8.12 to 3.8.14. - [Release notes](https://github.com/ijl/orjson/releases) - [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md) - [Commits](https://github.com/ijl/orjson/compare/3.8.12...3.8.14) --- updated-dependencies: - dependency-name: orjson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index cff54ca1c..f8c34100a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,7 +32,7 @@ py_find_1st==1.1.5 # Load ticker files 30% faster python-rapidjson==1.10 # Properly format api responses -orjson==3.8.12 +orjson==3.8.14 # Notify systemd sdnotify==0.3.2 From 35836479de24b98f1c375587949c99d251f807ae Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 May 2023 08:09:56 +0200 Subject: [PATCH 08/48] Bump requests pre-commit dependency --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4be298d7b..8a39a7773 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: additional_dependencies: - types-cachetools==5.3.0.5 - types-filelock==3.2.7 - - types-requests==2.30.0.0 + - types-requests==2.31.0.0 - types-tabulate==0.9.0.2 - types-python-dateutil==2.8.19.13 - SQLAlchemy==2.0.15 From 9f1bdc19aab3b2162a4df6cfff01aef53ceaf017 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 May 2023 08:10:29 +0200 Subject: [PATCH 09/48] Bump ruff pre-commit version --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4be298d7b..4724db36f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,7 +30,7 @@ repos: - repo: https://github.com/charliermarsh/ruff-pre-commit # Ruff version. - rev: 'v0.0.263' + rev: 'v0.0.270' hooks: - id: ruff From f074383d6a91933d224266189c54d7e46a936170 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 May 2023 17:24:04 +0200 Subject: [PATCH 10/48] Extract orderbook logic into separate method --- freqtrade/exchange/exchange.py | 36 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 3b1466c69..ac7306736 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1669,19 +1669,8 @@ class Exchange: order_book_top = conf_strategy.get('order_book_top', 1) if order_book is None: order_book = self.fetch_l2_order_book(pair, order_book_top) - logger.debug('order_book %s', order_book) - # top 1 = index 0 - try: - obside: OBLiteral = 'bids' if price_side == 'bid' else 'asks' - rate = order_book[obside][order_book_top - 1][0] - except (IndexError, KeyError) as e: - logger.warning( - f"{pair} - {name} Price at location {order_book_top} from orderbook " - f"could not be determined. Orderbook: {order_book}" - ) - raise PricingError from e - logger.debug(f"{pair} - {name} price from orderbook {price_side_word}" - f"side - top {order_book_top} order book {side} rate {rate:.8f}") + rate = self.get_rate_from_ob(pair, side, order_book, name, price_side, + order_book_top) else: logger.debug(f"Using Last {price_side_word} / Last Price") if ticker is None: @@ -1703,6 +1692,27 @@ class Exchange: return rate + def get_rate_from_ob(self, pair: str, side: EntryExit, order_book: OrderBook, name: str, + price_side: BidAsk, order_book_top: int) -> float: + """ + Get rate from orderbook + :raises: PricingError if rate could not be determined. + """ + logger.debug('order_book %s', order_book) + # top 1 = index 0 + try: + obside: OBLiteral = 'bids' if price_side == 'bid' else 'asks' + rate = order_book[obside][order_book_top - 1][0] + except (IndexError, KeyError) as e: + logger.warning( + f"{pair} - {name} Price at location {order_book_top} from orderbook " + f"could not be determined. Orderbook: {order_book}" + ) + raise PricingError from e + logger.debug(f"{pair} - {name} price from orderbook {price_side.capitalize()}" + f"side - top {order_book_top} order book {side} rate {rate:.8f}") + return rate + def get_rates(self, pair: str, refresh: bool, is_short: bool) -> Tuple[float, float]: entry_rate = None exit_rate = None From af1dbf7dffd6effc7746233fbfdb1f8664fa02ba Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 May 2023 17:27:11 +0200 Subject: [PATCH 11/48] Extract get_rate_from_ticker from get_rate method --- freqtrade/exchange/exchange.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index ac7306736..0406146cd 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1669,21 +1669,13 @@ class Exchange: order_book_top = conf_strategy.get('order_book_top', 1) if order_book is None: order_book = self.fetch_l2_order_book(pair, order_book_top) - rate = self.get_rate_from_ob(pair, side, order_book, name, price_side, - order_book_top) + rate = self._get_rate_from_ob(pair, side, order_book, name, price_side, + order_book_top) else: logger.debug(f"Using Last {price_side_word} / Last Price") if ticker is None: ticker = self.fetch_ticker(pair) - ticker_rate = ticker[price_side] - if ticker['last'] and ticker_rate: - if side == 'entry' and ticker_rate > ticker['last']: - balance = conf_strategy.get('price_last_balance', 0.0) - ticker_rate = ticker_rate + balance * (ticker['last'] - ticker_rate) - elif side == 'exit' and ticker_rate < ticker['last']: - balance = conf_strategy.get('price_last_balance', 0.0) - ticker_rate = ticker_rate - balance * (ticker_rate - ticker['last']) - rate = ticker_rate + rate = self._get_rate_from_ticker(side, ticker, conf_strategy, price_side) if rate is None: raise PricingError(f"{name}-Rate for {pair} was empty.") @@ -1692,8 +1684,24 @@ class Exchange: return rate - def get_rate_from_ob(self, pair: str, side: EntryExit, order_book: OrderBook, name: str, - price_side: BidAsk, order_book_top: int) -> float: + def _get_rate_from_ticker(self, side: EntryExit, ticker: Ticker, conf_strategy: Dict[str, Any], + price_side: BidAsk) -> Optional[float]: + """ + Get rate from ticker. + """ + ticker_rate = ticker[price_side] + if ticker['last'] and ticker_rate: + if side == 'entry' and ticker_rate > ticker['last']: + balance = conf_strategy.get('price_last_balance', 0.0) + ticker_rate = ticker_rate + balance * (ticker['last'] - ticker_rate) + elif side == 'exit' and ticker_rate < ticker['last']: + balance = conf_strategy.get('price_last_balance', 0.0) + ticker_rate = ticker_rate - balance * (ticker_rate - ticker['last']) + rate = ticker_rate + return rate + + def _get_rate_from_ob(self, pair: str, side: EntryExit, order_book: OrderBook, name: str, + price_side: BidAsk, order_book_top: int) -> float: """ Get rate from orderbook :raises: PricingError if rate could not be determined. From b666c418bbb7d9903ca20676f12f39574753062a Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 May 2023 17:33:11 +0200 Subject: [PATCH 12/48] Don't use variables for simple debug values --- freqtrade/exchange/exchange.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 0406146cd..6edaf2661 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1662,8 +1662,6 @@ class Exchange: price_side = self._get_price_side(side, is_short, conf_strategy) - price_side_word = price_side.capitalize() - if conf_strategy.get('use_order_book', False): order_book_top = conf_strategy.get('order_book_top', 1) @@ -1672,7 +1670,7 @@ class Exchange: rate = self._get_rate_from_ob(pair, side, order_book, name, price_side, order_book_top) else: - logger.debug(f"Using Last {price_side_word} / Last Price") + logger.debug(f"Using Last {price_side.capitalize()} / Last Price") if ticker is None: ticker = self.fetch_ticker(pair) rate = self._get_rate_from_ticker(side, ticker, conf_strategy, price_side) From 1f543666f427d664098e39a4605df5174fbd2345 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 31 May 2023 11:46:31 +0200 Subject: [PATCH 13/48] Improve test for reload-markets timings, fix bug closes #8714 --- freqtrade/exchange/exchange.py | 2 +- tests/exchange/test_exchange.py | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 6edaf2661..88022e19c 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -191,7 +191,7 @@ class Exchange: # Converts the interval provided in minutes in config to seconds self.markets_refresh_interval: int = exchange_conf.get( - "markets_refresh_interval", 60) * 60 + "markets_refresh_interval", 60) * 60 * 1000 if self.trading_mode != TradingMode.SPOT and load_leverage_tiers: self.fill_leverage_tiers() diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index ef70c8ba1..f022a0905 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -633,21 +633,23 @@ def test__load_markets(default_conf, mocker, caplog): assert ex.markets == expected_return -def test_reload_markets(default_conf, mocker, caplog): +def test_reload_markets(default_conf, mocker, caplog, time_machine): caplog.set_level(logging.DEBUG) initial_markets = {'ETH/BTC': {}} updated_markets = {'ETH/BTC': {}, "LTC/BTC": {}} - + start_dt = dt_now() + time_machine.move_to(start_dt, tick=False) api_mock = MagicMock() api_mock.load_markets = MagicMock(return_value=initial_markets) default_conf['exchange']['markets_refresh_interval'] = 10 exchange = get_patched_exchange(mocker, default_conf, api_mock, id="binance", mock_markets=False) exchange._load_async_markets = MagicMock() - exchange._last_markets_refresh = dt_ts() + assert exchange._last_markets_refresh == dt_ts() assert exchange.markets == initial_markets + time_machine.move_to(start_dt + timedelta(minutes=8), tick=False) # less than 10 minutes have passed, no reload exchange.reload_markets() assert exchange.markets == initial_markets @@ -655,12 +657,18 @@ def test_reload_markets(default_conf, mocker, caplog): api_mock.load_markets = MagicMock(return_value=updated_markets) # more than 10 minutes have passed, reload is executed - exchange._last_markets_refresh = dt_ts(dt_now() - timedelta(minutes=15)) + time_machine.move_to(start_dt + timedelta(minutes=11), tick=False) exchange.reload_markets() assert exchange.markets == updated_markets assert exchange._load_async_markets.call_count == 1 assert log_has('Performing scheduled market reload..', caplog) + # Not called again + exchange._load_async_markets.reset_mock() + + exchange.reload_markets() + assert exchange._load_async_markets.call_count == 0 + def test_reload_markets_exception(default_conf, mocker, caplog): caplog.set_level(logging.DEBUG) From 193d88c9c85190a0cc6a501bd12dec578d226060 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 31 May 2023 14:12:03 +0200 Subject: [PATCH 14/48] Double-check cancelling stop order didn't close the trade --- freqtrade/freqtradebot.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index fc4c65caf..42ac85fdb 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1302,6 +1302,10 @@ class FreqtradeBot(LoggingMixin): f"(orderid:{order['id']}) in order to add another one ...") self.cancel_stoploss_on_exchange(trade) + if not trade.is_open: + logger.warning( + f"Trade {trade} is closed, not creating trailing stoploss order.") + return # Create new stoploss order if not self.create_stoploss_order(trade=trade, stop_price=stoploss_norm): From 5311614d54dadb38747f74c605f5040d2a4cd438 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 31 May 2023 14:31:45 +0200 Subject: [PATCH 15/48] Update force exit wording --- freqtrade/rpc/rpc.py | 6 +++--- tests/rpc/test_rpc.py | 10 +++++----- tests/rpc/test_rpc_apiserver.py | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index dedb35503..6e1cc2b76 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -802,12 +802,12 @@ class RPC: with self._freqtrade._exit_lock: if trade_id == 'all': - # Execute sell for all open orders + # Execute exit for all open orders for trade in Trade.get_open_trades(): self.__exec_force_exit(trade, ordertype) Trade.commit() self._freqtrade.wallets.update() - return {'result': 'Created sell orders for all open trades.'} + return {'result': 'Created exit orders for all open trades.'} # Query for trade trade = Trade.get_trades( @@ -820,7 +820,7 @@ class RPC: self.__exec_force_exit(trade, ordertype, amount) Trade.commit() self._freqtrade.wallets.update() - return {'result': f'Created sell order for trade {trade_id}.'} + return {'result': f'Created exit order for trade {trade_id}.'} def _force_entry_validations(self, pair: str, order_side: SignalDirection): if not self._freqtrade.config.get('force_entry_enable', False): diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 405727d8c..da5882cf1 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -703,15 +703,15 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: rpc._rpc_force_exit(None) msg = rpc._rpc_force_exit('all') - assert msg == {'result': 'Created sell orders for all open trades.'} + assert msg == {'result': 'Created exit orders for all open trades.'} freqtradebot.enter_positions() msg = rpc._rpc_force_exit('all') - assert msg == {'result': 'Created sell orders for all open trades.'} + assert msg == {'result': 'Created exit orders for all open trades.'} freqtradebot.enter_positions() msg = rpc._rpc_force_exit('2') - assert msg == {'result': 'Created sell order for trade 2.'} + assert msg == {'result': 'Created exit order for trade 2.'} freqtradebot.state = State.STOPPED with pytest.raises(RPCException, match=r'.*trader is not running*'): @@ -775,7 +775,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: ) # check that the trade is called, which is done by ensuring exchange.cancel_order is called msg = rpc._rpc_force_exit('4') - assert msg == {'result': 'Created sell order for trade 4.'} + assert msg == {'result': 'Created exit order for trade 4.'} assert cancel_order_mock.call_count == 2 assert trade.amount == amount @@ -795,7 +795,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: } ) msg = rpc._rpc_force_exit('3') - assert msg == {'result': 'Created sell order for trade 3.'} + assert msg == {'result': 'Created exit order for trade 3.'} # status quo, no exchange calls assert cancel_order_mock.call_count == 3 diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 842981ad0..5ba42f6ea 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1333,7 +1333,7 @@ def test_api_forceexit(botclient, mocker, ticker, fee, markets): rc = client_post(client, f"{BASE_URI}/forceexit", data={"tradeid": "5", "ordertype": "market", "amount": 23}) assert_response(rc) - assert rc.json() == {'result': 'Created sell order for trade 5.'} + assert rc.json() == {'result': 'Created exit order for trade 5.'} Trade.rollback() trade = Trade.get_trades([Trade.id == 5]).first() @@ -1343,7 +1343,7 @@ def test_api_forceexit(botclient, mocker, ticker, fee, markets): rc = client_post(client, f"{BASE_URI}/forceexit", data={"tradeid": "5"}) assert_response(rc) - assert rc.json() == {'result': 'Created sell order for trade 5.'} + assert rc.json() == {'result': 'Created exit order for trade 5.'} Trade.rollback() trade = Trade.get_trades([Trade.id == 5]).first() From 08d040db14c8cb196c63e361076179c24fbb4501 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 31 May 2023 14:59:41 +0200 Subject: [PATCH 16/48] Slightly update force_exit test --- tests/rpc/test_rpc.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index da5882cf1..ef5f0f78e 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -761,6 +761,8 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: freqtradebot.config['max_open_trades'] = 3 freqtradebot.enter_positions() + + cancel_order_mock.reset_mock() trade = Trade.session.scalars(select(Trade).filter(Trade.id == '2')).first() amount = trade.amount # make an limit-buy open trade, if there is no 'filled', don't sell it @@ -776,11 +778,12 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: # check that the trade is called, which is done by ensuring exchange.cancel_order is called msg = rpc._rpc_force_exit('4') assert msg == {'result': 'Created exit order for trade 4.'} - assert cancel_order_mock.call_count == 2 + assert cancel_order_mock.call_count == 1 assert trade.amount == amount + cancel_order_mock.reset_mock() trade = Trade.session.scalars(select(Trade).filter(Trade.id == '3')).first() - + amount = trade.amount # make an limit-sell open trade mocker.patch( f'{EXMS}.fetch_order', @@ -797,7 +800,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: msg = rpc._rpc_force_exit('3') assert msg == {'result': 'Created exit order for trade 3.'} # status quo, no exchange calls - assert cancel_order_mock.call_count == 3 + assert cancel_order_mock.call_count == 1 def test_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None: From 430cd24bbcb0e9ad9188a97c1b46bb5a279dd0f6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 31 May 2023 15:00:09 +0200 Subject: [PATCH 17/48] Invert order (exit trade 3 before trade 4) --- tests/rpc/test_rpc.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index ef5f0f78e..5a9e94e8d 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -762,25 +762,6 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: freqtradebot.config['max_open_trades'] = 3 freqtradebot.enter_positions() - cancel_order_mock.reset_mock() - trade = Trade.session.scalars(select(Trade).filter(Trade.id == '2')).first() - amount = trade.amount - # make an limit-buy open trade, if there is no 'filled', don't sell it - mocker.patch( - f'{EXMS}.fetch_order', - return_value={ - 'status': 'open', - 'type': 'limit', - 'side': 'buy', - 'filled': None - } - ) - # check that the trade is called, which is done by ensuring exchange.cancel_order is called - msg = rpc._rpc_force_exit('4') - assert msg == {'result': 'Created exit order for trade 4.'} - assert cancel_order_mock.call_count == 1 - assert trade.amount == amount - cancel_order_mock.reset_mock() trade = Trade.session.scalars(select(Trade).filter(Trade.id == '3')).first() amount = trade.amount @@ -802,6 +783,25 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: # status quo, no exchange calls assert cancel_order_mock.call_count == 1 + cancel_order_mock.reset_mock() + trade = Trade.session.scalars(select(Trade).filter(Trade.id == '2')).first() + amount = trade.amount + # make an limit-buy open trade, if there is no 'filled', don't sell it + mocker.patch( + f'{EXMS}.fetch_order', + return_value={ + 'status': 'open', + 'type': 'limit', + 'side': 'buy', + 'filled': None + } + ) + # check that the trade is called, which is done by ensuring exchange.cancel_order is called + msg = rpc._rpc_force_exit('4') + assert msg == {'result': 'Created exit order for trade 4.'} + assert cancel_order_mock.call_count == 1 + assert trade.amount == amount + def test_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) From 5fc8426b9bedc9e583b7cc5e876a530168136242 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 31 May 2023 17:06:51 +0200 Subject: [PATCH 18/48] Improve handling of order cancelation failures with force_exit closes #8708 --- freqtrade/rpc/rpc.py | 12 ++++++++++-- tests/rpc/test_rpc.py | 33 +++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 6e1cc2b76..c3759e03a 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -755,7 +755,7 @@ class RPC: return {'status': 'Reloaded from orders from exchange'} def __exec_force_exit(self, trade: Trade, ordertype: Optional[str], - amount: Optional[float] = None) -> None: + amount: Optional[float] = None) -> bool: # Check if there is there is an open order fully_canceled = False if trade.open_order_id: @@ -770,6 +770,9 @@ class RPC: self._freqtrade.handle_cancel_exit(trade, order, CANCEL_REASON['FORCE_EXIT']) if not fully_canceled: + if trade.open_order_id is not None: + # Order cancellation failed, so we can't exit. + return False # Get current rate and execute sell current_rate = self._freqtrade.exchange.get_rate( trade.pair, side='exit', is_short=trade.is_short, refresh=True) @@ -790,6 +793,9 @@ class RPC: trade, current_rate, exit_check, ordertype=order_type, sub_trade_amt=sub_amount) + return True + return False + def _rpc_force_exit(self, trade_id: str, ordertype: Optional[str] = None, *, amount: Optional[float] = None) -> Dict[str, str]: """ @@ -817,9 +823,11 @@ class RPC: logger.warning('force_exit: Invalid argument received') raise RPCException('invalid argument') - self.__exec_force_exit(trade, ordertype, amount) + result = self.__exec_force_exit(trade, ordertype, amount) Trade.commit() self._freqtrade.wallets.update() + if not result: + raise RPCException('Failed to exit trade.') return {'result': f'Created exit order for trade {trade_id}.'} def _force_entry_validations(self, pair: str, order_side: SignalDirection): diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 5a9e94e8d..31d7ae37b 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -765,7 +765,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: cancel_order_mock.reset_mock() trade = Trade.session.scalars(select(Trade).filter(Trade.id == '3')).first() amount = trade.amount - # make an limit-sell open trade + # make an limit-sell open order trade mocker.patch( f'{EXMS}.fetch_order', return_value={ @@ -778,12 +778,24 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: 'id': trade.orders[0].order_id, } ) + cancel_order_3 = mocker.patch( + f'{EXMS}.cancel_order_with_result', + return_value={ + 'status': 'canceled', + 'type': 'limit', + 'side': 'sell', + 'amount': amount, + 'remaining': amount, + 'filled': 0.0, + 'id': trade.orders[0].order_id, + } + ) msg = rpc._rpc_force_exit('3') assert msg == {'result': 'Created exit order for trade 3.'} # status quo, no exchange calls - assert cancel_order_mock.call_count == 1 + assert cancel_order_3.call_count == 1 + assert cancel_order_mock.call_count == 0 - cancel_order_mock.reset_mock() trade = Trade.session.scalars(select(Trade).filter(Trade.id == '2')).first() amount = trade.amount # make an limit-buy open trade, if there is no 'filled', don't sell it @@ -796,10 +808,23 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: 'filled': None } ) + cancel_order_4 = mocker.patch( + f'{EXMS}.cancel_order_with_result', + return_value={ + 'status': 'canceled', + 'type': 'limit', + 'side': 'sell', + 'amount': amount, + 'remaining': 0.0, + 'filled': amount, + 'id': trade.orders[0].order_id, + } + ) # check that the trade is called, which is done by ensuring exchange.cancel_order is called msg = rpc._rpc_force_exit('4') assert msg == {'result': 'Created exit order for trade 4.'} - assert cancel_order_mock.call_count == 1 + assert cancel_order_4.call_count == 1 + assert cancel_order_mock.call_count == 0 assert trade.amount == amount From 9c6fee384143683ae564ae39421532f8258ca9fa Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 31 May 2023 17:14:22 +0200 Subject: [PATCH 19/48] Enable gate futures for spread-filter again closes #8687 --- freqtrade/exchange/gate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/freqtrade/exchange/gate.py b/freqtrade/exchange/gate.py index 2ac135fc1..eceab4ec1 100644 --- a/freqtrade/exchange/gate.py +++ b/freqtrade/exchange/gate.py @@ -33,7 +33,6 @@ class Gate(Exchange): _ft_has_futures: Dict = { "needs_trading_fees": True, "marketOrderRequiresPrice": False, - "tickers_have_bid_ask": False, "fee_cost_in_contracts": False, # Set explicitly to false for clarity "order_props_in_contracts": ['amount', 'filled', 'remaining'], "stop_price_type_field": "price_type", From e0d9603e997a8386e3c46f61354c37a660786db3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jun 2023 07:03:07 +0200 Subject: [PATCH 20/48] Raise correct httperrorcode for webserver-only endpoitns --- freqtrade/rpc/api_server/deps.py | 5 +++-- tests/rpc/test_rpc_apiserver.py | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/freqtrade/rpc/api_server/deps.py b/freqtrade/rpc/api_server/deps.py index 8fd105d3e..4c118d274 100644 --- a/freqtrade/rpc/api_server/deps.py +++ b/freqtrade/rpc/api_server/deps.py @@ -1,7 +1,7 @@ from typing import Any, AsyncIterator, Dict, Optional from uuid import uuid4 -from fastapi import Depends +from fastapi import Depends, HTTPException from freqtrade.enums import RunMode from freqtrade.persistence import Trade @@ -57,5 +57,6 @@ def get_message_stream(): def is_webserver_mode(config=Depends(get_config)): if config['runmode'] != RunMode.WEBSERVER: - raise RPCException('Bot is not in the correct state') + raise HTTPException(status_code=503, + detail='Bot is not in the correct state.') return None diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 5ba42f6ea..cdf620b90 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1673,7 +1673,8 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir): rc = client_get(client, f"{BASE_URI}/backtest") # Backtest prevented in default mode - assert_response(rc, 502) + assert_response(rc, 503) + assert rc.json()['detail'] == 'Bot is not in the correct state.' ftbot.config['runmode'] = RunMode.WEBSERVER # Backtesting not started yet @@ -1812,7 +1813,9 @@ def test_api_backtest_history(botclient, mocker, testdatadir): ]) rc = client_get(client, f"{BASE_URI}/backtest/history") - assert_response(rc, 502) + assert_response(rc, 503) + assert rc.json()['detail'] == 'Bot is not in the correct state.' + ftbot.config['user_data_dir'] = testdatadir ftbot.config['runmode'] = RunMode.WEBSERVER From 8aee368f60a4629dd50e1e1479aa91ae394d4f0f Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jun 2023 07:07:02 +0200 Subject: [PATCH 21/48] auto-inject webserver mode dependency --- freqtrade/rpc/api_server/api_backtest.py | 17 ++++++++--------- freqtrade/rpc/api_server/webserver.py | 4 +++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/freqtrade/rpc/api_server/api_backtest.py b/freqtrade/rpc/api_server/api_backtest.py index 8fa1a87b8..411ba4978 100644 --- a/freqtrade/rpc/api_server/api_backtest.py +++ b/freqtrade/rpc/api_server/api_backtest.py @@ -16,14 +16,14 @@ from freqtrade.exchange.common import remove_exchange_credentials from freqtrade.misc import deep_merge_dicts from freqtrade.rpc.api_server.api_schemas import (BacktestHistoryEntry, BacktestRequest, BacktestResponse) -from freqtrade.rpc.api_server.deps import get_config, is_webserver_mode +from freqtrade.rpc.api_server.deps import get_config from freqtrade.rpc.api_server.webserver_bgwork import ApiBG from freqtrade.rpc.rpc import RPCException logger = logging.getLogger(__name__) -# Private API, protected by authentication +# Private API, protected by authentication and webserver_mode dependency router = APIRouter() @@ -102,7 +102,7 @@ def __run_backtest_bg(btconfig: Config): @router.post('/backtest', response_model=BacktestResponse, tags=['webserver', 'backtest']) async def api_start_backtest( bt_settings: BacktestRequest, background_tasks: BackgroundTasks, - config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): + config=Depends(get_config)): ApiBG.bt['bt_error'] = None """Start backtesting if not done so already""" if ApiBG.bgtask_running: @@ -143,7 +143,7 @@ async def api_start_backtest( @router.get('/backtest', response_model=BacktestResponse, tags=['webserver', 'backtest']) -def api_get_backtest(ws_mode=Depends(is_webserver_mode)): +def api_get_backtest(): """ Get backtesting result. Returns Result after backtesting has been ran. @@ -188,7 +188,7 @@ def api_get_backtest(ws_mode=Depends(is_webserver_mode)): @router.delete('/backtest', response_model=BacktestResponse, tags=['webserver', 'backtest']) -def api_delete_backtest(ws_mode=Depends(is_webserver_mode)): +def api_delete_backtest(): """Reset backtesting""" if ApiBG.bgtask_running: return { @@ -215,7 +215,7 @@ def api_delete_backtest(ws_mode=Depends(is_webserver_mode)): @router.get('/backtest/abort', response_model=BacktestResponse, tags=['webserver', 'backtest']) -def api_backtest_abort(ws_mode=Depends(is_webserver_mode)): +def api_backtest_abort(): if not ApiBG.bgtask_running: return { "status": "not_running", @@ -236,15 +236,14 @@ def api_backtest_abort(ws_mode=Depends(is_webserver_mode)): @router.get('/backtest/history', response_model=List[BacktestHistoryEntry], tags=['webserver', 'backtest']) -def api_backtest_history(config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): +def api_backtest_history(config=Depends(get_config)): # Get backtest result history, read from metadata files return get_backtest_resultlist(config['user_data_dir'] / 'backtest_results') @router.get('/backtest/history/result', response_model=BacktestResponse, tags=['webserver', 'backtest']) -def api_backtest_history_result(filename: str, strategy: str, config=Depends(get_config), - ws_mode=Depends(is_webserver_mode)): +def api_backtest_history_result(filename: str, strategy: str, config=Depends(get_config)): # Get backtest result history, read from metadata files fn = config['user_data_dir'] / 'backtest_results' / filename results: Dict[str, Any] = { diff --git a/freqtrade/rpc/api_server/webserver.py b/freqtrade/rpc/api_server/webserver.py index 165849a7f..ea623e0ed 100644 --- a/freqtrade/rpc/api_server/webserver.py +++ b/freqtrade/rpc/api_server/webserver.py @@ -118,6 +118,7 @@ class ApiServer(RPCHandler): from freqtrade.rpc.api_server.api_v1 import router as api_v1 from freqtrade.rpc.api_server.api_v1 import router_public as api_v1_public from freqtrade.rpc.api_server.api_ws import router as ws_router + from freqtrade.rpc.api_server.deps import is_webserver_mode from freqtrade.rpc.api_server.web_ui import router_ui app.include_router(api_v1_public, prefix="/api/v1") @@ -126,7 +127,8 @@ class ApiServer(RPCHandler): dependencies=[Depends(http_basic_or_jwt_token)], ) app.include_router(api_backtest, prefix="/api/v1", - dependencies=[Depends(http_basic_or_jwt_token)], + dependencies=[Depends(http_basic_or_jwt_token), + Depends(is_webserver_mode)], ) app.include_router(ws_router, prefix="/api/v1") app.include_router(router_login, prefix="/api/v1", tags=["auth"]) From 30dd63fcb91cbfa6281a2456cf4a0330a4ac7038 Mon Sep 17 00:00:00 2001 From: Robert Caulk Date: Thu, 1 Jun 2023 15:54:05 +0200 Subject: [PATCH 22/48] Update freqai.md --- docs/freqai.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/freqai.md b/docs/freqai.md index 3c4f47212..a1b20ae1e 100644 --- a/docs/freqai.md +++ b/docs/freqai.md @@ -76,7 +76,7 @@ pip install -r requirements-freqai.txt ### Usage with docker -If you are using docker, a dedicated tag with FreqAI dependencies is available as `:freqai`. As such - you can replace the image line in your docker compose file with `image: freqtradeorg/freqtrade:develop_freqai`. This image contains the regular FreqAI dependencies. Similar to native installs, Catboost will not be available on ARM based devices. +If you are using docker, a dedicated tag with FreqAI dependencies is available as `:freqai`. As such - you can replace the image line in your docker compose file with `image: freqtradeorg/freqtrade:develop_freqai`. This image contains the regular FreqAI dependencies. Similar to native installs, Catboost will not be available on ARM based devices. If you would like to use PyTorch or Reinforcement learning, you should use the torch or RL tags, `image: freqtradeorg/freqtrade:develop_freqaitorch`, `image: freqtradeorg/freqtrade:develop_freqairl`. !!! note "docker-compose-freqai.yml" We do provide an explicit docker-compose file for this in `docker/docker-compose-freqai.yml` - which can be used via `docker compose -f docker/docker-compose-freqai.yml run ...` - or can be copied to replace the original docker file. This docker-compose file also contains a (disabled) section to enable GPU resources within docker containers. This obviously assumes the system has GPU resources available. From d0f900f567fe7a7269de51e641aed2d09460a281 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jun 2023 20:09:59 +0200 Subject: [PATCH 23/48] set HTTPX level to warning closes #8717 --- freqtrade/loggers/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/loggers/__init__.py b/freqtrade/loggers/__init__.py index 58f207608..dc01e4e5b 100644 --- a/freqtrade/loggers/__init__.py +++ b/freqtrade/loggers/__init__.py @@ -32,7 +32,7 @@ def _set_loggers(verbosity: int = 0, api_verbosity: str = 'info') -> None: logging.INFO if verbosity <= 2 else logging.DEBUG ) logging.getLogger('telegram').setLevel(logging.INFO) - logging.getLogger('httpx').setLevel(logging.INFO) + logging.getLogger('httpx').setLevel(logging.WARNING) logging.getLogger('werkzeug').setLevel( logging.ERROR if api_verbosity == 'error' else logging.INFO From 565c0496d9c6cbf0cf81998f7037e2e2d2392000 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jun 2023 20:10:57 +0200 Subject: [PATCH 24/48] Bump httpx min requirement --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 1cd4dce1f..d04774361 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ aiohttp==3.8.4 SQLAlchemy==2.0.15 python-telegram-bot==20.3 # can't be hard-pinned due to telegram-bot pinning httpx with ~ -httpx>=0.23.3 +httpx>=0.24.1 arrow==1.2.3 cachetools==5.3.1 requests==2.31.0 diff --git a/setup.py b/setup.py index f8b8b515c..106b5b6d3 100644 --- a/setup.py +++ b/setup.py @@ -107,7 +107,7 @@ setup( 'ast-comments', 'aiohttp', 'cryptography', - 'httpx', + 'httpx>=0.24.1', 'python-dateutil', 'packaging', ], From 49c0fdf367de05f1f38c5e07d7ced0b5d9a17cdb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jun 2023 20:23:40 +0000 Subject: [PATCH 25/48] Bump cryptography from 40.0.1 to 41.0.0 Bumps [cryptography](https://github.com/pyca/cryptography) from 40.0.1 to 41.0.0. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/40.0.1...41.0.0) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d04774361..8f5ee3b3a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ pandas-ta==0.3.14b ccxt==3.1.13 cryptography==40.0.2; platform_machine != 'armv7l' -cryptography==40.0.1; platform_machine == 'armv7l' +cryptography==41.0.0; platform_machine == 'armv7l' aiohttp==3.8.4 SQLAlchemy==2.0.15 python-telegram-bot==20.3 From e890bc0718b8cd73e247247c79ea1dbeb9b42d09 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 08:30:38 +0200 Subject: [PATCH 26/48] Don't bump pi version, but bump regular version --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 8f5ee3b3a..b25e28046 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,8 +3,8 @@ pandas==2.0.1 pandas-ta==0.3.14b ccxt==3.1.13 -cryptography==40.0.2; platform_machine != 'armv7l' -cryptography==41.0.0; platform_machine == 'armv7l' +cryptography==41.0.1; platform_machine != 'armv7l' +cryptography==40.0.1; platform_machine == 'armv7l' aiohttp==3.8.4 SQLAlchemy==2.0.15 python-telegram-bot==20.3 From b5d10177794ac97882bcd6186bc6dc1ec005f092 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 07:15:05 +0200 Subject: [PATCH 27/48] Update list_exchanges to use a dict internally --- freqtrade/commands/list_commands.py | 11 ++++++++--- freqtrade/exchange/exchange_utils.py | 10 +++++++--- freqtrade/exchange/types.py | 8 ++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/freqtrade/commands/list_commands.py b/freqtrade/commands/list_commands.py index 3358f8cc8..d81800896 100644 --- a/freqtrade/commands/list_commands.py +++ b/freqtrade/commands/list_commands.py @@ -28,15 +28,20 @@ def start_list_exchanges(args: Dict[str, Any]) -> None: exchanges = validate_exchanges(args['list_exchanges_all']) if args['print_one_column']: - print('\n'.join([e[0] for e in exchanges])) + print('\n'.join([e['name'] for e in exchanges])) else: if args['list_exchanges_all']: print("All exchanges supported by the ccxt library:") else: print("Exchanges available for Freqtrade:") - exchanges = [e for e in exchanges if e[1] is not False] + exchanges = [e for e in exchanges if e['valid'] is not False] - print(tabulate(exchanges, headers=['Exchange name', 'Valid', 'reason'])) + headers = { + 'name': 'Exchange name', + 'valid': 'Valid', + 'comment': 'reason', + } + print(tabulate(exchanges, headers=headers)) def _print_objs_tabular(objs: List, print_colorized: bool) -> None: diff --git a/freqtrade/exchange/exchange_utils.py b/freqtrade/exchange/exchange_utils.py index c6c2d5a24..32a68a959 100644 --- a/freqtrade/exchange/exchange_utils.py +++ b/freqtrade/exchange/exchange_utils.py @@ -10,6 +10,7 @@ from ccxt import (DECIMAL_PLACES, ROUND, ROUND_DOWN, ROUND_UP, SIGNIFICANT_DIGIT TRUNCATE, decimal_to_precision) from freqtrade.exchange.common import BAD_EXCHANGES, EXCHANGE_HAS_OPTIONAL, EXCHANGE_HAS_REQUIRED +from freqtrade.exchange.types import ValidExchangesType from freqtrade.util import FtPrecise from freqtrade.util.datetime_helpers import dt_from_ts, dt_ts @@ -55,14 +56,17 @@ def validate_exchange(exchange: str) -> Tuple[bool, str]: return True, '' -def validate_exchanges(all_exchanges: bool) -> List[Tuple[str, bool, str]]: +def validate_exchanges(all_exchanges: bool) -> List[ValidExchangesType]: """ :return: List of tuples with exchangename, valid, reason. """ exchanges = ccxt_exchanges() if all_exchanges else available_exchanges() - exchanges_valid = [ - (e, *validate_exchange(e)) for e in exchanges + + exchanges_valid: List[ValidExchangesType] = [ + {'name': e, 'valid': valid, 'comment': comment} + for e, valid, comment in ((e, *validate_exchange(e)) for e in exchanges) ] + return exchanges_valid diff --git a/freqtrade/exchange/types.py b/freqtrade/exchange/types.py index 5568e4336..b20c51201 100644 --- a/freqtrade/exchange/types.py +++ b/freqtrade/exchange/types.py @@ -26,5 +26,13 @@ class OrderBook(TypedDict): Tickers = Dict[str, Ticker] + +# Used for list-exchanges +class ValidExchangesType(TypedDict): + name: str + valid: bool + comment: str + + # pair, timeframe, candleType, OHLCV, drop last?, OHLCVResponse = Tuple[str, str, CandleType, List, bool] From 250ae2d0061cd60bd121a4658a5013b3930feeb0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 08:28:44 +0200 Subject: [PATCH 28/48] Enhance list-exchanges with more information --- freqtrade/commands/list_commands.py | 34 +++++++++++++++++------- freqtrade/exchange/exchange_utils.py | 31 ++++++++++++++++++--- freqtrade/resolvers/exchange_resolver.py | 26 +++++++++++++++++- freqtrade/resolvers/iresolver.py | 2 +- 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/freqtrade/commands/list_commands.py b/freqtrade/commands/list_commands.py index d81800896..dadab7b9b 100644 --- a/freqtrade/commands/list_commands.py +++ b/freqtrade/commands/list_commands.py @@ -30,18 +30,34 @@ def start_list_exchanges(args: Dict[str, Any]) -> None: if args['print_one_column']: print('\n'.join([e['name'] for e in exchanges])) else: - if args['list_exchanges_all']: - print("All exchanges supported by the ccxt library:") - else: - print("Exchanges available for Freqtrade:") - exchanges = [e for e in exchanges if e['valid'] is not False] - headers = { 'name': 'Exchange name', 'valid': 'Valid', - 'comment': 'reason', - } - print(tabulate(exchanges, headers=headers)) + 'supported': 'Supported', + 'trade_modes': 'Markets', + 'comment': 'Reason', + } + + def build_entry(exchange, valid): + valid_entry = {'valid': exchange['valid']} if valid else {} + result = { + 'name': exchange['name'], + **valid_entry, + 'supported': 'Official' if exchange['supported'] else '', + 'trade_modes': ', '.join(exchange['trade_modes']), + 'comment': exchange['comment'], + } + + return result + + if args['list_exchanges_all']: + print("All exchanges supported by the ccxt library:") + exchanges = [build_entry(e, True) for e in exchanges] + else: + print("Exchanges available for Freqtrade:") + exchanges = [build_entry(e, False) for e in exchanges if e['valid'] is not False] + + print(tabulate(exchanges, headers=headers, )) def _print_objs_tabular(objs: List, print_colorized: bool) -> None: diff --git a/freqtrade/exchange/exchange_utils.py b/freqtrade/exchange/exchange_utils.py index 32a68a959..05f701136 100644 --- a/freqtrade/exchange/exchange_utils.py +++ b/freqtrade/exchange/exchange_utils.py @@ -9,7 +9,8 @@ import ccxt from ccxt import (DECIMAL_PLACES, ROUND, ROUND_DOWN, ROUND_UP, SIGNIFICANT_DIGITS, TICK_SIZE, TRUNCATE, decimal_to_precision) -from freqtrade.exchange.common import BAD_EXCHANGES, EXCHANGE_HAS_OPTIONAL, EXCHANGE_HAS_REQUIRED +from freqtrade.exchange.common import (BAD_EXCHANGES, EXCHANGE_HAS_OPTIONAL, EXCHANGE_HAS_REQUIRED, + SUPPORTED_EXCHANGES) from freqtrade.exchange.types import ValidExchangesType from freqtrade.util import FtPrecise from freqtrade.util.datetime_helpers import dt_from_ts, dt_ts @@ -56,15 +57,39 @@ def validate_exchange(exchange: str) -> Tuple[bool, str]: return True, '' +def build_exchange_list_entry( + exchange_name: str, exchangeClasses: Dict[str, Any]) -> ValidExchangesType: + valid, comment = validate_exchange(exchange_name) + result = { + 'name': exchange_name, + 'valid': valid, + 'supported': exchange_name.lower() in SUPPORTED_EXCHANGES, + 'comment': comment, + 'trade_modes': ['spot'], + } + if resolved := exchangeClasses.get(exchange_name.lower()): + supported_modes = ['spot'] + [ + f"{mm.value} {tm.value}" + for tm, mm in resolved['class']._supported_trading_mode_margin_pairs + ] + result.update({ + 'trade_modes': supported_modes, + }) + + return result + + def validate_exchanges(all_exchanges: bool) -> List[ValidExchangesType]: """ :return: List of tuples with exchangename, valid, reason. """ exchanges = ccxt_exchanges() if all_exchanges else available_exchanges() + from freqtrade.resolvers.exchange_resolver import ExchangeResolver + + subclassed = {e['name'].lower(): e for e in ExchangeResolver.search_all_objects({}, False)} exchanges_valid: List[ValidExchangesType] = [ - {'name': e, 'valid': valid, 'comment': comment} - for e, valid, comment in ((e, *validate_exchange(e)) for e in exchanges) + build_exchange_list_entry(e, subclassed) for e in exchanges ] return exchanges_valid diff --git a/freqtrade/resolvers/exchange_resolver.py b/freqtrade/resolvers/exchange_resolver.py index c5c4e1a68..2f912c4ab 100644 --- a/freqtrade/resolvers/exchange_resolver.py +++ b/freqtrade/resolvers/exchange_resolver.py @@ -2,7 +2,8 @@ This module loads custom exchanges """ import logging -from typing import Optional +from inspect import isclass +from typing import Any, Dict, List, Optional import freqtrade.exchange as exchanges from freqtrade.constants import Config, ExchangeConfig @@ -72,3 +73,26 @@ class ExchangeResolver(IResolver): f"Impossible to load Exchange '{exchange_name}'. This class does not exist " "or contains Python code errors." ) + + @classmethod + def search_all_objects(cls, config: Config, enum_failed: bool, + recursive: bool = False) -> List[Dict[str, Any]]: + """ + Searches for valid objects + :param config: Config object + :param enum_failed: If True, will return None for modules which fail. + Otherwise, failing modules are skipped. + :param recursive: Recursively walk directory tree searching for strategies + :return: List of dicts containing 'name', 'class' and 'location' entries + """ + result = [] + for exchange_name in dir(exchanges): + exchange = getattr(exchanges, exchange_name) + if isclass(exchange) and issubclass(exchange, Exchange): + result.append({ + 'name': exchange_name, + 'class': exchange, + 'location': exchange.__module__, + 'location_rel: ': exchange.__module__.replace('freqtrade.', ''), + }) + return result diff --git a/freqtrade/resolvers/iresolver.py b/freqtrade/resolvers/iresolver.py index 2b20560e2..1557f0f35 100644 --- a/freqtrade/resolvers/iresolver.py +++ b/freqtrade/resolvers/iresolver.py @@ -41,7 +41,7 @@ class IResolver: object_type: Type[Any] object_type_str: str user_subdir: Optional[str] = None - initial_search_path: Optional[Path] + initial_search_path: Optional[Path] = None # Optional config setting containing a path (strategy_path, freqaimodel_path) extra_path: Optional[str] = None From fcb960185eb350daa25178b1d390cb9992378898 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 08:36:14 +0200 Subject: [PATCH 29/48] Clarify function naming --- freqtrade/commands/list_commands.py | 4 ++-- freqtrade/exchange/__init__.py | 10 +++++----- freqtrade/exchange/exchange_utils.py | 2 +- tests/test_main.py | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/freqtrade/commands/list_commands.py b/freqtrade/commands/list_commands.py index dadab7b9b..2970c1fc3 100644 --- a/freqtrade/commands/list_commands.py +++ b/freqtrade/commands/list_commands.py @@ -11,7 +11,7 @@ from tabulate import tabulate from freqtrade.configuration import setup_utils_configuration from freqtrade.enums import RunMode from freqtrade.exceptions import OperationalException -from freqtrade.exchange import market_is_active, validate_exchanges +from freqtrade.exchange import list_available_exchanges, market_is_active from freqtrade.misc import parse_db_uri_for_logging, plural from freqtrade.resolvers import ExchangeResolver, StrategyResolver @@ -25,7 +25,7 @@ def start_list_exchanges(args: Dict[str, Any]) -> None: :param args: Cli args from Arguments() :return: None """ - exchanges = validate_exchanges(args['list_exchanges_all']) + exchanges = list_available_exchanges(args['list_exchanges_all']) if args['print_one_column']: print('\n'.join([e['name'] for e in exchanges])) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 12fb0c55e..9ac31a0d8 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -13,11 +13,11 @@ from freqtrade.exchange.exchange_utils import (ROUND_DOWN, ROUND_UP, amount_to_c amount_to_contracts, amount_to_precision, available_exchanges, ccxt_exchanges, contracts_to_amount, date_minus_candles, - is_exchange_known_ccxt, market_is_active, - price_to_precision, timeframe_to_minutes, - timeframe_to_msecs, timeframe_to_next_date, - timeframe_to_prev_date, timeframe_to_seconds, - validate_exchange, validate_exchanges) + is_exchange_known_ccxt, list_available_exchanges, + market_is_active, price_to_precision, + timeframe_to_minutes, timeframe_to_msecs, + timeframe_to_next_date, timeframe_to_prev_date, + timeframe_to_seconds, validate_exchange) from freqtrade.exchange.gate import Gate from freqtrade.exchange.hitbtc import Hitbtc from freqtrade.exchange.huobi import Huobi diff --git a/freqtrade/exchange/exchange_utils.py b/freqtrade/exchange/exchange_utils.py index 05f701136..cbb7f7733 100644 --- a/freqtrade/exchange/exchange_utils.py +++ b/freqtrade/exchange/exchange_utils.py @@ -79,7 +79,7 @@ def build_exchange_list_entry( return result -def validate_exchanges(all_exchanges: bool) -> List[ValidExchangesType]: +def list_available_exchanges(all_exchanges: bool) -> List[ValidExchangesType]: """ :return: List of tuples with exchangename, valid, reason. """ diff --git a/tests/test_main.py b/tests/test_main.py index 59a5bb0f7..bdb3c2bba 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -118,7 +118,7 @@ def test_main_operational_exception(mocker, default_conf, caplog) -> None: def test_main_operational_exception1(mocker, default_conf, caplog) -> None: patch_exchange(mocker) mocker.patch( - 'freqtrade.commands.list_commands.validate_exchanges', + 'freqtrade.commands.list_commands.list_available_exchanges', MagicMock(side_effect=ValueError('Oh snap!')) ) patched_configuration_load_config_file(mocker, default_conf) @@ -132,7 +132,7 @@ def test_main_operational_exception1(mocker, default_conf, caplog) -> None: assert log_has('Fatal exception!', caplog) assert not log_has_re(r'SIGINT.*', caplog) mocker.patch( - 'freqtrade.commands.list_commands.validate_exchanges', + 'freqtrade.commands.list_commands.list_available_exchanges', MagicMock(side_effect=KeyboardInterrupt) ) with pytest.raises(SystemExit): From cc04f3279ae31339c1177d8143fd7d41d60540ce Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 08:47:46 +0200 Subject: [PATCH 30/48] bump pre-commit mypy version --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index eb50a3a3f..67e7ece19 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: # stages: [push] - repo: https://github.com/pre-commit/mirrors-mypy - rev: "v1.0.1" + rev: "v1.3.0" hooks: - id: mypy exclude: build_helpers From 6f928b826f8f9a75072c86ca1cb9a3d027882611 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 08:49:16 +0200 Subject: [PATCH 31/48] Update types for build_exchange_list_entry --- freqtrade/exchange/exchange_utils.py | 6 +++--- freqtrade/exchange/types.py | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/exchange_utils.py b/freqtrade/exchange/exchange_utils.py index cbb7f7733..a57b2406c 100644 --- a/freqtrade/exchange/exchange_utils.py +++ b/freqtrade/exchange/exchange_utils.py @@ -57,10 +57,10 @@ def validate_exchange(exchange: str) -> Tuple[bool, str]: return True, '' -def build_exchange_list_entry( +def _build_exchange_list_entry( exchange_name: str, exchangeClasses: Dict[str, Any]) -> ValidExchangesType: valid, comment = validate_exchange(exchange_name) - result = { + result: ValidExchangesType = { 'name': exchange_name, 'valid': valid, 'supported': exchange_name.lower() in SUPPORTED_EXCHANGES, @@ -89,7 +89,7 @@ def list_available_exchanges(all_exchanges: bool) -> List[ValidExchangesType]: subclassed = {e['name'].lower(): e for e in ExchangeResolver.search_all_objects({}, False)} exchanges_valid: List[ValidExchangesType] = [ - build_exchange_list_entry(e, subclassed) for e in exchanges + _build_exchange_list_entry(e, subclassed) for e in exchanges ] return exchanges_valid diff --git a/freqtrade/exchange/types.py b/freqtrade/exchange/types.py index b20c51201..13030986e 100644 --- a/freqtrade/exchange/types.py +++ b/freqtrade/exchange/types.py @@ -31,7 +31,9 @@ Tickers = Dict[str, Ticker] class ValidExchangesType(TypedDict): name: str valid: bool + supported: bool comment: str + trade_modes: List[str] # pair, timeframe, candleType, OHLCV, drop last?, From 54bf1634c7c51acdb35134056336056a152d19bb Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 09:04:40 +0200 Subject: [PATCH 32/48] Refactor validExchangesType to separate types package --- freqtrade/exchange/exchange_utils.py | 2 +- freqtrade/exchange/types.py | 9 --------- freqtrade/types/__init__.py | 1 + freqtrade/types/valid_exchanges_type.py | 10 ++++++++++ 4 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 freqtrade/types/__init__.py create mode 100644 freqtrade/types/valid_exchanges_type.py diff --git a/freqtrade/exchange/exchange_utils.py b/freqtrade/exchange/exchange_utils.py index a57b2406c..1f1e926ee 100644 --- a/freqtrade/exchange/exchange_utils.py +++ b/freqtrade/exchange/exchange_utils.py @@ -11,7 +11,7 @@ from ccxt import (DECIMAL_PLACES, ROUND, ROUND_DOWN, ROUND_UP, SIGNIFICANT_DIGIT from freqtrade.exchange.common import (BAD_EXCHANGES, EXCHANGE_HAS_OPTIONAL, EXCHANGE_HAS_REQUIRED, SUPPORTED_EXCHANGES) -from freqtrade.exchange.types import ValidExchangesType +from freqtrade.types import ValidExchangesType from freqtrade.util import FtPrecise from freqtrade.util.datetime_helpers import dt_from_ts, dt_ts diff --git a/freqtrade/exchange/types.py b/freqtrade/exchange/types.py index 13030986e..1247e5754 100644 --- a/freqtrade/exchange/types.py +++ b/freqtrade/exchange/types.py @@ -27,14 +27,5 @@ class OrderBook(TypedDict): Tickers = Dict[str, Ticker] -# Used for list-exchanges -class ValidExchangesType(TypedDict): - name: str - valid: bool - supported: bool - comment: str - trade_modes: List[str] - - # pair, timeframe, candleType, OHLCV, drop last?, OHLCVResponse = Tuple[str, str, CandleType, List, bool] diff --git a/freqtrade/types/__init__.py b/freqtrade/types/__init__.py new file mode 100644 index 000000000..11fe6354b --- /dev/null +++ b/freqtrade/types/__init__.py @@ -0,0 +1 @@ +from freqtrade.types.valid_exchanges_type import ValidExchangesType # noqa: F401 diff --git a/freqtrade/types/valid_exchanges_type.py b/freqtrade/types/valid_exchanges_type.py new file mode 100644 index 000000000..f40c3fb30 --- /dev/null +++ b/freqtrade/types/valid_exchanges_type.py @@ -0,0 +1,10 @@ +# Used for list-exchanges +from typing import List, TypedDict + + +class ValidExchangesType(TypedDict): + name: str + valid: bool + supported: bool + comment: str + trade_modes: List[str] From 74254bb8936f9da1ee0f90f89b02d77eae3664f3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 09:20:01 +0200 Subject: [PATCH 33/48] Add /exchanges endpoint to list available exchanges --- freqtrade/rpc/api_server/api_schemas.py | 5 ++++ freqtrade/rpc/api_server/api_v1.py | 12 ++++++++- tests/rpc/test_rpc_apiserver.py | 33 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index a081f9fe9..e218465fc 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -5,6 +5,7 @@ from pydantic import BaseModel from freqtrade.constants import DATETIME_PRINT_FORMAT, IntOrInf from freqtrade.enums import OrderTypeValues, SignalDirection, TradingMode +from freqtrade.types import ValidExchangesType class Ping(BaseModel): @@ -396,6 +397,10 @@ class StrategyListResponse(BaseModel): strategies: List[str] +class ExchangeListResponse(BaseModel): + exchanges: List[ValidExchangesType] + + class FreqAIModelListResponse(BaseModel): freqaimodels: List[str] diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index 2354c4bf8..6af6d7709 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -12,7 +12,8 @@ from freqtrade.exceptions import OperationalException from freqtrade.rpc import RPC from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, BlacklistPayload, BlacklistResponse, Count, Daily, - DeleteLockRequest, DeleteTrade, ForceEnterPayload, + DeleteLockRequest, DeleteTrade, + ExchangeListResponse, ForceEnterPayload, ForceEnterResponse, ForceExitPayload, FreqAIModelListResponse, Health, Locks, Logs, OpenTradeSchema, PairHistory, PerformanceEntry, @@ -312,6 +313,15 @@ def get_strategy(strategy: str, config=Depends(get_config)): } +@router.get('/exchanges', response_model=ExchangeListResponse, tags=[]) +def list_exchanges(config=Depends(get_config)): + from freqtrade.exchange import list_available_exchanges + exchanges = list_available_exchanges(config) + return { + 'exchanges': exchanges, + } + + @router.get('/freqaimodels', response_model=FreqAIModelListResponse, tags=['freqai']) def list_freqaimodels(config=Depends(get_config)): from freqtrade.resolvers.freqaimodel_resolver import FreqaiModelResolver diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index cdf620b90..8377de547 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1578,6 +1578,38 @@ def test_api_strategy(botclient): assert_response(rc, 500) +def test_api_exchanges(botclient): + ftbot, client = botclient + + rc = client_get(client, f"{BASE_URI}/exchanges") + assert_response(rc) + response = rc.json() + assert isinstance(response['exchanges'], list) + assert len(response['exchanges']) > 20 + okx = [x for x in response['exchanges'] if x['name'] == 'okx'][0] + assert okx == { + "name": "okx", + "valid": True, + "supported": True, + "comment": "", + "trade_modes": [ + "spot", + "isolated futures", + ] + } + + mexc = [x for x in response['exchanges'] if x['name'] == 'mexc'][0] + assert mexc == { + "name": "mexc", + "valid": True, + "supported": False, + "comment": "", + "trade_modes": [ + "spot", + ] + } + + def test_api_freqaimodels(botclient, tmpdir, mocker): ftbot, client = botclient ftbot.config['user_data_dir'] = Path(tmpdir) @@ -1933,3 +1965,4 @@ def test_api_ws_send_msg(default_conf, mocker, caplog): finally: ApiServer.shutdown() + ApiServer.shutdown() From 72f4e1475c968923a9b476cbee4dd89c69808048 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 09:20:36 +0200 Subject: [PATCH 34/48] Bump api version --- freqtrade/rpc/api_server/api_v1.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index 6af6d7709..6c0ea04aa 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -47,7 +47,8 @@ logger = logging.getLogger(__name__) # 2.26: increase /balance output # 2.27: Add /trades//reload endpoint # 2.28: Switch reload endpoint to Post -API_VERSION = 2.28 +# 2.29: Add /exchanges endpoint +API_VERSION = 2.29 # Public API, requires no auth. router_public = APIRouter() From ac7419e9754e97678b93ac5644f175dcd92edbca Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 11:46:01 +0200 Subject: [PATCH 35/48] Split trademode response value into trade_mode and margin-mode --- freqtrade/commands/list_commands.py | 12 ++++++++---- freqtrade/exchange/exchange_utils.py | 6 +++--- freqtrade/exchange/types.py | 1 - freqtrade/types/valid_exchanges_type.py | 7 ++++++- tests/rpc/test_rpc_apiserver.py | 17 +++++++++++++---- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/freqtrade/commands/list_commands.py b/freqtrade/commands/list_commands.py index 2970c1fc3..dcb102ce5 100644 --- a/freqtrade/commands/list_commands.py +++ b/freqtrade/commands/list_commands.py @@ -1,7 +1,7 @@ import csv import logging import sys -from typing import Any, Dict, List +from typing import Any, Dict, List, Union import rapidjson from colorama import Fore, Style @@ -14,6 +14,7 @@ from freqtrade.exceptions import OperationalException from freqtrade.exchange import list_available_exchanges, market_is_active from freqtrade.misc import parse_db_uri_for_logging, plural from freqtrade.resolvers import ExchangeResolver, StrategyResolver +from freqtrade.types import ValidExchangesType logger = logging.getLogger(__name__) @@ -38,13 +39,16 @@ def start_list_exchanges(args: Dict[str, Any]) -> None: 'comment': 'Reason', } - def build_entry(exchange, valid): + def build_entry(exchange: ValidExchangesType, valid: bool): valid_entry = {'valid': exchange['valid']} if valid else {} - result = { + result: Dict[str, Union[str, bool]] = { 'name': exchange['name'], **valid_entry, 'supported': 'Official' if exchange['supported'] else '', - 'trade_modes': ', '.join(exchange['trade_modes']), + 'trade_modes': ', '.join( + (f"{a['margin_mode']} " if a['margin_mode'] else '') + a['trading_mode'] + for a in exchange['trade_modes'] + ), 'comment': exchange['comment'], } diff --git a/freqtrade/exchange/exchange_utils.py b/freqtrade/exchange/exchange_utils.py index 1f1e926ee..fe7264dd9 100644 --- a/freqtrade/exchange/exchange_utils.py +++ b/freqtrade/exchange/exchange_utils.py @@ -65,11 +65,11 @@ def _build_exchange_list_entry( 'valid': valid, 'supported': exchange_name.lower() in SUPPORTED_EXCHANGES, 'comment': comment, - 'trade_modes': ['spot'], + 'trade_modes': [{'trading_mode': 'spot', 'margin_mode': ''}], } if resolved := exchangeClasses.get(exchange_name.lower()): - supported_modes = ['spot'] + [ - f"{mm.value} {tm.value}" + supported_modes = [{'trading_mode': 'spot', 'margin_mode': ''}] + [ + {'trading_mode': tm.value, 'margin_mode': mm.value} for tm, mm in resolved['class']._supported_trading_mode_margin_pairs ] result.update({ diff --git a/freqtrade/exchange/types.py b/freqtrade/exchange/types.py index 1247e5754..5568e4336 100644 --- a/freqtrade/exchange/types.py +++ b/freqtrade/exchange/types.py @@ -26,6 +26,5 @@ class OrderBook(TypedDict): Tickers = Dict[str, Ticker] - # pair, timeframe, candleType, OHLCV, drop last?, OHLCVResponse = Tuple[str, str, CandleType, List, bool] diff --git a/freqtrade/types/valid_exchanges_type.py b/freqtrade/types/valid_exchanges_type.py index f40c3fb30..0f02b1f5d 100644 --- a/freqtrade/types/valid_exchanges_type.py +++ b/freqtrade/types/valid_exchanges_type.py @@ -2,9 +2,14 @@ from typing import List, TypedDict +class TradeModeType(TypedDict): + trading_mode: str + margin_mode: str + + class ValidExchangesType(TypedDict): name: str valid: bool supported: bool comment: str - trade_modes: List[str] + trade_modes: List[TradeModeType] diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 8377de547..ac7904515 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1593,8 +1593,14 @@ def test_api_exchanges(botclient): "supported": True, "comment": "", "trade_modes": [ - "spot", - "isolated futures", + { + "trading_mode": "spot", + "margin_mode": "" + }, + { + "trading_mode": "futures", + "margin_mode": "isolated" + } ] } @@ -1605,8 +1611,11 @@ def test_api_exchanges(botclient): "supported": False, "comment": "", "trade_modes": [ - "spot", - ] + { + "trading_mode": "spot", + "margin_mode": "" + } + ] } From 12e31208e126ba5ecde2e0f561a57954935a81a9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Jun 2023 12:33:44 +0200 Subject: [PATCH 36/48] Update typedDict type used with pydantic --- freqtrade/types/valid_exchanges_type.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/freqtrade/types/valid_exchanges_type.py b/freqtrade/types/valid_exchanges_type.py index 0f02b1f5d..c01149455 100644 --- a/freqtrade/types/valid_exchanges_type.py +++ b/freqtrade/types/valid_exchanges_type.py @@ -1,5 +1,7 @@ # Used for list-exchanges -from typing import List, TypedDict +from typing import List + +from typing_extensions import TypedDict class TradeModeType(TypedDict): From 7a726da691c7a87412774515e775a2b7fe8c22ea Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 4 Jun 2023 20:28:08 +0200 Subject: [PATCH 37/48] Update cached binance leverage tiers --- .../exchange/binance_leverage_tiers.json | 1154 ++++++++++------- 1 file changed, 699 insertions(+), 455 deletions(-) diff --git a/freqtrade/exchange/binance_leverage_tiers.json b/freqtrade/exchange/binance_leverage_tiers.json index 0f252f63e..b211be701 100644 --- a/freqtrade/exchange/binance_leverage_tiers.json +++ b/freqtrade/exchange/binance_leverage_tiers.json @@ -120,10 +120,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 20.0, + "maxLeverage": 10.0, "info": { "bracket": "1", - "initialLeverage": "20", + "initialLeverage": "10", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.02", @@ -136,10 +136,10 @@ "minNotional": 5000.0, "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 10.0, + "maxLeverage": 8.0, "info": { "bracket": "2", - "initialLeverage": "10", + "initialLeverage": "8", "notionalCap": "25000", "notionalFloor": "5000", "maintMarginRatio": "0.025", @@ -152,10 +152,10 @@ "minNotional": 25000.0, "maxNotional": 100000.0, "maintenanceMarginRate": 0.05, - "maxLeverage": 8.0, + "maxLeverage": 6.0, "info": { "bracket": "3", - "initialLeverage": "8", + "initialLeverage": "6", "notionalCap": "100000", "notionalFloor": "25000", "maintMarginRatio": "0.05", @@ -198,13 +198,13 @@ "tier": 6.0, "currency": "BUSD", "minNotional": 1000000.0, - "maxNotional": 5000000.0, + "maxNotional": 1500000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "5000000", + "notionalCap": "1500000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386900.0" @@ -332,120 +332,6 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.02", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 15.0, - "info": { - "bracket": "2", - "initialLeverage": "15", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "25.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 600000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "600000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "650.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 600000.0, - "maxNotional": 1600000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "1600000", - "notionalFloor": "600000", - "maintMarginRatio": "0.1", - "cum": "30650.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 1600000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "5", - "initialLeverage": "4", - "notionalCap": "2000000", - "notionalFloor": "1600000", - "maintMarginRatio": "0.125", - "cum": "70650.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 6000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "6000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.25", - "cum": "320650.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 6000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "10000000", - "notionalFloor": "6000000", - "maintMarginRatio": "0.5", - "cum": "1820650.0" - } - } - ], - "1000SHIB/BUSD:BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.02, "maxLeverage": 25.0, "info": { "bracket": "1", @@ -456,16 +342,130 @@ "cum": "0.0" } }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "50000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 900000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "900000", + "notionalFloor": "50000", + "maintMarginRatio": "0.05", + "cum": "1275.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 900000.0, + "maxNotional": 2400000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "2400000", + "notionalFloor": "900000", + "maintMarginRatio": "0.1", + "cum": "46275.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 2400000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "3000000", + "notionalFloor": "2400000", + "maintMarginRatio": "0.125", + "cum": "106275.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 3000000.0, + "maxNotional": 9000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "9000000", + "notionalFloor": "3000000", + "maintMarginRatio": "0.25", + "cum": "481275.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 9000000.0, + "maxNotional": 15000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "15000000", + "notionalFloor": "9000000", + "maintMarginRatio": "0.5", + "cum": "2731275.0" + } + } + ], + "1000SHIB/BUSD:BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 10.0, + "info": { + "bracket": "1", + "initialLeverage": "10", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, { "tier": 2.0, "currency": "BUSD", "minNotional": 5000.0, "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 15.0, + "maxLeverage": 8.0, "info": { "bracket": "2", - "initialLeverage": "15", + "initialLeverage": "8", "notionalCap": "25000", "notionalFloor": "5000", "maintMarginRatio": "0.025", @@ -478,10 +478,10 @@ "minNotional": 25000.0, "maxNotional": 100000.0, "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "maxLeverage": 6.0, "info": { "bracket": "3", - "initialLeverage": "10", + "initialLeverage": "6", "notionalCap": "100000", "notionalFloor": "25000", "maintMarginRatio": "0.05", @@ -540,13 +540,13 @@ "tier": 7.0, "currency": "BUSD", "minNotional": 3000000.0, - "maxNotional": 8000000.0, + "maxNotional": 3500000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "8000000", + "notionalCap": "3500000", "notionalFloor": "3000000", "maintMarginRatio": "0.5", "cum": "949400.0" @@ -590,13 +590,13 @@ "tier": 3.0, "currency": "USDT", "minNotional": 25000.0, - "maxNotional": 50000.0, + "maxNotional": 100000.0, "maintenanceMarginRate": 0.01, "maxLeverage": 25.0, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "50000", + "notionalCap": "100000", "notionalFloor": "25000", "maintMarginRatio": "0.01", "cum": "67.5" @@ -605,87 +605,87 @@ { "tier": 4.0, "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, + "minNotional": 100000.0, + "maxNotional": 300000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "4", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "notionalCap": "300000", + "notionalFloor": "100000", "maintMarginRatio": "0.025", - "cum": "817.5" + "cum": "1567.5" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, + "minNotional": 300000.0, + "maxNotional": 750000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "5", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "notionalCap": "750000", + "notionalFloor": "300000", "maintMarginRatio": "0.05", - "cum": "4567.5" + "cum": "9067.5" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, + "minNotional": 750000.0, + "maxNotional": 1500000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "notionalCap": "1500000", + "notionalFloor": "750000", "maintMarginRatio": "0.1", - "cum": "17067.5" + "cum": "46567.5" } }, { "tier": 7.0, "currency": "USDT", - "minNotional": 500000.0, - "maxNotional": 1000000.0, + "minNotional": 1500000.0, + "maxNotional": 3000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, "info": { "bracket": "7", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "notionalCap": "3000000", + "notionalFloor": "1500000", "maintMarginRatio": "0.125", - "cum": "29567.5" + "cum": "84067.5" } }, { "tier": 8.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, + "minNotional": 3000000.0, + "maxNotional": 6000000.0, "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "notionalCap": "6000000", + "notionalFloor": "3000000", "maintMarginRatio": "0.25", - "cum": "154567.5" + "cum": "459067.5" } }, { "tier": 9.0, "currency": "USDT", - "minNotional": 2000000.0, + "minNotional": 6000000.0, "maxNotional": 30000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, @@ -693,9 +693,9 @@ "bracket": "9", "initialLeverage": "1", "notionalCap": "30000000", - "notionalFloor": "2000000", + "notionalFloor": "6000000", "maintMarginRatio": "0.5", - "cum": "654567.5" + "cum": "1959067.5" } } ], @@ -1978,10 +1978,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 20.0, + "maxLeverage": 10.0, "info": { "bracket": "1", - "initialLeverage": "20", + "initialLeverage": "10", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.02", @@ -1994,10 +1994,10 @@ "minNotional": 5000.0, "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 15.0, + "maxLeverage": 8.0, "info": { "bracket": "2", - "initialLeverage": "15", + "initialLeverage": "8", "notionalCap": "25000", "notionalFloor": "5000", "maintMarginRatio": "0.025", @@ -2010,10 +2010,10 @@ "minNotional": 25000.0, "maxNotional": 200000.0, "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "maxLeverage": 6.0, "info": { "bracket": "3", - "initialLeverage": "10", + "initialLeverage": "6", "notionalCap": "200000", "notionalFloor": "25000", "maintMarginRatio": "0.05", @@ -2072,13 +2072,13 @@ "tier": 7.0, "currency": "USDT", "minNotional": 3000000.0, - "maxNotional": 5000000.0, + "maxNotional": 3500000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "5000000", + "notionalCap": "3500000", "notionalFloor": "3000000", "maintMarginRatio": "0.5", "cum": "898150.0" @@ -3132,13 +3132,13 @@ "tier": 3.0, "currency": "USDT", "minNotional": 50000.0, - "maxNotional": 400000.0, + "maxNotional": 600000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "3", "initialLeverage": "20", - "notionalCap": "400000", + "notionalCap": "600000", "notionalFloor": "50000", "maintMarginRatio": "0.025", "cum": "770.0" @@ -3147,39 +3147,39 @@ { "tier": 4.0, "currency": "USDT", - "minNotional": 400000.0, - "maxNotional": 800000.0, + "minNotional": 600000.0, + "maxNotional": 1200000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "800000", - "notionalFloor": "400000", + "notionalCap": "1200000", + "notionalFloor": "600000", "maintMarginRatio": "0.05", - "cum": "10770.0" + "cum": "15770.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 800000.0, - "maxNotional": 2000000.0, + "minNotional": 1200000.0, + "maxNotional": 3000000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "800000", + "notionalCap": "3000000", + "notionalFloor": "1200000", "maintMarginRatio": "0.1", - "cum": "50770.0" + "cum": "75770.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 2000000.0, + "minNotional": 3000000.0, "maxNotional": 5000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, @@ -3187,9 +3187,9 @@ "bracket": "6", "initialLeverage": "4", "notionalCap": "5000000", - "notionalFloor": "2000000", + "notionalFloor": "3000000", "maintMarginRatio": "0.125", - "cum": "100770.0" + "cum": "150770.0" } }, { @@ -3205,7 +3205,7 @@ "notionalCap": "12000000", "notionalFloor": "5000000", "maintMarginRatio": "0.25", - "cum": "725770.0" + "cum": "775770.0" } }, { @@ -3221,7 +3221,7 @@ "notionalCap": "20000000", "notionalFloor": "12000000", "maintMarginRatio": "0.5", - "cum": "3725770.0" + "cum": "3775770.0" } } ], @@ -4874,13 +4874,13 @@ "tier": 2.0, "currency": "USDT", "minNotional": 5000.0, - "maxNotional": 25000.0, + "maxNotional": 50000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 10.0, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "25000", + "notionalCap": "50000", "notionalFloor": "5000", "maintMarginRatio": "0.025", "cum": "25.0" @@ -4889,65 +4889,81 @@ { "tier": 3.0, "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, + "minNotional": 50000.0, + "maxNotional": 200000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 8.0, "info": { "bracket": "3", "initialLeverage": "8", - "notionalCap": "100000", - "notionalFloor": "25000", + "notionalCap": "200000", + "notionalFloor": "50000", "maintMarginRatio": "0.05", - "cum": "650.0" + "cum": "1275.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, + "minNotional": 200000.0, + "maxNotional": 500000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "notionalCap": "500000", + "notionalFloor": "200000", "maintMarginRatio": "0.1", - "cum": "5650.0" + "cum": "11275.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 250000.0, + "minNotional": 500000.0, "maxNotional": 1000000.0, "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, + "maxLeverage": 4.0, "info": { "bracket": "5", - "initialLeverage": "2", + "initialLeverage": "4", "notionalCap": "1000000", - "notionalFloor": "250000", + "notionalFloor": "500000", "maintMarginRatio": "0.125", - "cum": "11900.0" + "cum": "23775.0" } }, { "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 2000000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "148775.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { - "bracket": "6", + "bracket": "7", "initialLeverage": "1", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "notionalCap": "3000000", + "notionalFloor": "1500000", "maintMarginRatio": "0.5", - "cum": "386900.0" + "cum": "523775.0" } } ], @@ -6714,13 +6730,13 @@ "tier": 2.0, "currency": "USDT", "minNotional": 5000.0, - "maxNotional": 25000.0, + "maxNotional": 50000.0, "maintenanceMarginRate": 0.015, "maxLeverage": 25.0, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "25000", + "notionalCap": "50000", "notionalFloor": "5000", "maintMarginRatio": "0.015", "cum": "25.0" @@ -6729,23 +6745,23 @@ { "tier": 3.0, "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 300000.0, + "minNotional": 50000.0, + "maxNotional": 400000.0, "maintenanceMarginRate": 0.02, "maxLeverage": 20.0, "info": { "bracket": "3", "initialLeverage": "20", - "notionalCap": "300000", - "notionalFloor": "25000", + "notionalCap": "400000", + "notionalFloor": "50000", "maintMarginRatio": "0.02", - "cum": "150.0" + "cum": "275.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 300000.0, + "minNotional": 400000.0, "maxNotional": 1200000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, @@ -6753,9 +6769,9 @@ "bracket": "4", "initialLeverage": "10", "notionalCap": "1200000", - "notionalFloor": "300000", + "notionalFloor": "400000", "maintMarginRatio": "0.05", - "cum": "9150.0" + "cum": "12275.0" } }, { @@ -6771,7 +6787,7 @@ "notionalCap": "3000000", "notionalFloor": "1200000", "maintMarginRatio": "0.1", - "cum": "69150.0" + "cum": "72275.0" } }, { @@ -6787,7 +6803,7 @@ "notionalCap": "6000000", "notionalFloor": "3000000", "maintMarginRatio": "0.125", - "cum": "144150.0" + "cum": "147275.0" } }, { @@ -6803,7 +6819,7 @@ "notionalCap": "18000000", "notionalFloor": "6000000", "maintMarginRatio": "0.25", - "cum": "894150.0" + "cum": "897275.0" } }, { @@ -6819,7 +6835,7 @@ "notionalCap": "30000000", "notionalFloor": "18000000", "maintMarginRatio": "0.5", - "cum": "5394150.0" + "cum": "5397275.0" } } ], @@ -7140,10 +7156,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 20.0, + "maxLeverage": 8.0, "info": { "bracket": "1", - "initialLeverage": "20", + "initialLeverage": "8", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.02", @@ -7156,10 +7172,10 @@ "minNotional": 5000.0, "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 15.0, + "maxLeverage": 7.0, "info": { "bracket": "2", - "initialLeverage": "15", + "initialLeverage": "7", "notionalCap": "25000", "notionalFloor": "5000", "maintMarginRatio": "0.025", @@ -7172,10 +7188,10 @@ "minNotional": 25000.0, "maxNotional": 100000.0, "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "maxLeverage": 6.0, "info": { "bracket": "3", - "initialLeverage": "10", + "initialLeverage": "6", "notionalCap": "100000", "notionalFloor": "25000", "maintMarginRatio": "0.05", @@ -7218,19 +7234,133 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 5000000.0, + "maxNotional": 1500000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "5000000", + "notionalCap": "1500000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386900.0" } } ], + "COMBO/USDT:USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 15.0, + "info": { + "bracket": "2", + "initialLeverage": "15", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "1000000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "3000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "148150.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 3000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "3000000", + "maintMarginRatio": "0.5", + "cum": "898150.0" + } + } + ], "COMP/USDT:USDT": [ { "tier": 1.0, @@ -10152,13 +10282,13 @@ "tier": 4.0, "currency": "USDT", "minNotional": 50000.0, - "maxNotional": 250000.0, + "maxNotional": 400000.0, "maintenanceMarginRate": 0.02, "maxLeverage": 25.0, "info": { "bracket": "4", "initialLeverage": "25", - "notionalCap": "250000", + "notionalCap": "400000", "notionalFloor": "50000", "maintMarginRatio": "0.02", "cum": "545.0" @@ -10167,39 +10297,39 @@ { "tier": 5.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, + "minNotional": 400000.0, + "maxNotional": 2000000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "5", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "notionalCap": "2000000", + "notionalFloor": "400000", "maintMarginRatio": "0.05", - "cum": "8045.0" + "cum": "12545.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 5000000.0, + "minNotional": 2000000.0, + "maxNotional": 8000000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "5000000", - "notionalFloor": "1000000", + "notionalCap": "8000000", + "notionalFloor": "2000000", "maintMarginRatio": "0.1", - "cum": "58045.0" + "cum": "112545.0" } }, { "tier": 7.0, "currency": "USDT", - "minNotional": 5000000.0, + "minNotional": 8000000.0, "maxNotional": 10000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, @@ -10207,9 +10337,9 @@ "bracket": "7", "initialLeverage": "4", "notionalCap": "10000000", - "notionalFloor": "5000000", + "notionalFloor": "8000000", "maintMarginRatio": "0.125", - "cum": "183045.0" + "cum": "312545.0" } }, { @@ -10225,7 +10355,7 @@ "notionalCap": "20000000", "notionalFloor": "10000000", "maintMarginRatio": "0.15", - "cum": "433045.0" + "cum": "562545.0" } }, { @@ -10241,7 +10371,7 @@ "notionalCap": "30000000", "notionalFloor": "20000000", "maintMarginRatio": "0.25", - "cum": "2433045.0" + "cum": "2562545.0" } }, { @@ -10257,7 +10387,7 @@ "notionalCap": "50000000", "notionalFloor": "30000000", "maintMarginRatio": "0.5", - "cum": "9933045.0" + "cum": "1.0062545E7" } } ], @@ -10268,10 +10398,10 @@ "minNotional": 0.0, "maxNotional": 5.0, "maintenanceMarginRate": 0.005, - "maxLeverage": 75.0, + "maxLeverage": 100.0, "info": { "bracket": "1", - "initialLeverage": "75", + "initialLeverage": "100", "notionalCap": "5", "notionalFloor": "0", "maintMarginRatio": "0.005", @@ -10284,10 +10414,10 @@ "minNotional": 5.0, "maxNotional": 10.0, "maintenanceMarginRate": 0.006, - "maxLeverage": 50.0, + "maxLeverage": 75.0, "info": { "bracket": "2", - "initialLeverage": "50", + "initialLeverage": "75", "notionalCap": "10", "notionalFloor": "5", "maintMarginRatio": "0.006", @@ -10300,10 +10430,10 @@ "minNotional": 10.0, "maxNotional": 100.0, "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, + "maxLeverage": 50.0, "info": { "bracket": "3", - "initialLeverage": "25", + "initialLeverage": "50", "notionalCap": "100", "notionalFloor": "10", "maintMarginRatio": "0.01", @@ -10314,13 +10444,13 @@ "tier": 4.0, "currency": "BTC", "minNotional": 100.0, - "maxNotional": 250.0, + "maxNotional": 400.0, "maintenanceMarginRate": 0.02, "maxLeverage": 20.0, "info": { "bracket": "4", "initialLeverage": "20", - "notionalCap": "250", + "notionalCap": "400", "notionalFloor": "100", "maintMarginRatio": "0.02", "cum": "1.045" @@ -10329,7 +10459,7 @@ { "tier": 5.0, "currency": "BTC", - "minNotional": 250.0, + "minNotional": 400.0, "maxNotional": 800.0, "maintenanceMarginRate": 0.025, "maxLeverage": 10.0, @@ -10337,9 +10467,9 @@ "bracket": "5", "initialLeverage": "10", "notionalCap": "800", - "notionalFloor": "250", + "notionalFloor": "400", "maintMarginRatio": "0.025", - "cum": "2.295" + "cum": "3.045" } }, { @@ -10355,7 +10485,7 @@ "notionalCap": "1500", "notionalFloor": "800", "maintMarginRatio": "0.05", - "cum": "22.295" + "cum": "23.045" } }, { @@ -10371,7 +10501,7 @@ "notionalCap": "2000", "notionalFloor": "1500", "maintMarginRatio": "0.1", - "cum": "97.295" + "cum": "98.045" } }, { @@ -10387,7 +10517,7 @@ "notionalCap": "3000", "notionalFloor": "2000", "maintMarginRatio": "0.125", - "cum": "147.295" + "cum": "148.045" } }, { @@ -10403,7 +10533,7 @@ "notionalCap": "5000", "notionalFloor": "3000", "maintMarginRatio": "0.25", - "cum": "522.295" + "cum": "523.045" } }, { @@ -10419,7 +10549,7 @@ "notionalCap": "10000", "notionalFloor": "5000", "maintMarginRatio": "0.5", - "cum": "1772.295" + "cum": "1773.045" } } ], @@ -12594,13 +12724,13 @@ "tier": 3.0, "currency": "USDT", "minNotional": 150000.0, - "maxNotional": 250000.0, + "maxNotional": 600000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", + "notionalCap": "600000", "notionalFloor": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" @@ -12609,55 +12739,55 @@ { "tier": 4.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, + "minNotional": 600000.0, + "maxNotional": 1600000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "notionalCap": "1600000", + "notionalFloor": "600000", "maintMarginRatio": "0.1", - "cum": "17000.0" + "cum": "34500.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 500000.0, - "maxNotional": 1000000.0, + "minNotional": 1600000.0, + "maxNotional": 2000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "notionalCap": "2000000", + "notionalFloor": "1600000", "maintMarginRatio": "0.125", - "cum": "29500.0" + "cum": "74500.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, + "minNotional": 2000000.0, + "maxNotional": 4000000.0, "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "notionalCap": "4000000", + "notionalFloor": "2000000", "maintMarginRatio": "0.25", - "cum": "154500.0" + "cum": "324500.0" } }, { "tier": 7.0, "currency": "USDT", - "minNotional": 2000000.0, + "minNotional": 4000000.0, "maxNotional": 30000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, @@ -12665,9 +12795,9 @@ "bracket": "7", "initialLeverage": "1", "notionalCap": "30000000", - "notionalFloor": "2000000", + "notionalFloor": "4000000", "maintMarginRatio": "0.5", - "cum": "654500.0" + "cum": "1324500.0" } } ], @@ -14937,6 +15067,120 @@ } } ], + "KEY/USDT:USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 15.0, + "info": { + "bracket": "2", + "initialLeverage": "15", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "1000000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "3000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "148150.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 3000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "3000000", + "maintMarginRatio": "0.5", + "cum": "898150.0" + } + } + ], "KLAY/USDT:USDT": [ { "tier": 1.0, @@ -15694,10 +15938,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, + "maxLeverage": 20.0, "info": { "bracket": "1", - "initialLeverage": "25", + "initialLeverage": "20", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.02", @@ -15710,10 +15954,10 @@ "minNotional": 5000.0, "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, + "maxLeverage": 15.0, "info": { "bracket": "2", - "initialLeverage": "20", + "initialLeverage": "15", "notionalCap": "25000", "notionalFloor": "5000", "maintMarginRatio": "0.025", @@ -15772,13 +16016,13 @@ "tier": 6.0, "currency": "USDT", "minNotional": 3000000.0, - "maxNotional": 9000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "9000000", + "notionalCap": "5000000", "notionalFloor": "3000000", "maintMarginRatio": "0.25", "cum": "480650.0" @@ -15787,17 +16031,17 @@ { "tier": 7.0, "currency": "USDT", - "minNotional": 9000000.0, - "maxNotional": 15000000.0, + "minNotional": 5000000.0, + "maxNotional": 7000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "15000000", - "notionalFloor": "9000000", + "notionalCap": "7000000", + "notionalFloor": "5000000", "maintMarginRatio": "0.5", - "cum": "2730650.0" + "cum": "1730650.0" } } ], @@ -15808,10 +16052,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, + "maxLeverage": 10.0, "info": { "bracket": "1", - "initialLeverage": "25", + "initialLeverage": "10", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.02", @@ -15824,10 +16068,10 @@ "minNotional": 5000.0, "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 15.0, + "maxLeverage": 8.0, "info": { "bracket": "2", - "initialLeverage": "15", + "initialLeverage": "8", "notionalCap": "25000", "notionalFloor": "5000", "maintMarginRatio": "0.025", @@ -15840,10 +16084,10 @@ "minNotional": 25000.0, "maxNotional": 100000.0, "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "maxLeverage": 6.0, "info": { "bracket": "3", - "initialLeverage": "10", + "initialLeverage": "6", "notionalCap": "100000", "notionalFloor": "25000", "maintMarginRatio": "0.05", @@ -15902,13 +16146,13 @@ "tier": 7.0, "currency": "BUSD", "minNotional": 3000000.0, - "maxNotional": 8000000.0, + "maxNotional": 4000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "8000000", + "notionalCap": "4000000", "notionalFloor": "3000000", "maintMarginRatio": "0.5", "cum": "949400.0" @@ -16636,13 +16880,13 @@ "tier": 4.0, "currency": "USDT", "minNotional": 50000.0, - "maxNotional": 250000.0, + "maxNotional": 500000.0, "maintenanceMarginRate": 0.02, "maxLeverage": 25.0, "info": { "bracket": "4", "initialLeverage": "25", - "notionalCap": "250000", + "notionalCap": "500000", "notionalFloor": "50000", "maintMarginRatio": "0.02", "cum": "545.0" @@ -16651,39 +16895,39 @@ { "tier": 5.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, + "minNotional": 500000.0, + "maxNotional": 2000000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "5", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "notionalCap": "2000000", + "notionalFloor": "500000", "maintMarginRatio": "0.05", - "cum": "8045.0" + "cum": "15545.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 5000000.0, + "minNotional": 2000000.0, + "maxNotional": 8000000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "5000000", - "notionalFloor": "1000000", + "notionalCap": "8000000", + "notionalFloor": "2000000", "maintMarginRatio": "0.1", - "cum": "58045.0" + "cum": "115545.0" } }, { "tier": 7.0, "currency": "USDT", - "minNotional": 5000000.0, + "minNotional": 8000000.0, "maxNotional": 10000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, @@ -16691,9 +16935,9 @@ "bracket": "7", "initialLeverage": "4", "notionalCap": "10000000", - "notionalFloor": "5000000", + "notionalFloor": "8000000", "maintMarginRatio": "0.125", - "cum": "183045.0" + "cum": "315545.0" } }, { @@ -16709,7 +16953,7 @@ "notionalCap": "20000000", "notionalFloor": "10000000", "maintMarginRatio": "0.15", - "cum": "433045.0" + "cum": "565545.0" } }, { @@ -16725,7 +16969,7 @@ "notionalCap": "30000000", "notionalFloor": "20000000", "maintMarginRatio": "0.25", - "cum": "2433045.0" + "cum": "2565545.0" } }, { @@ -16741,7 +16985,7 @@ "notionalCap": "50000000", "notionalFloor": "30000000", "maintMarginRatio": "0.5", - "cum": "9933045.0" + "cum": "1.0065545E7" } } ], @@ -18198,13 +18442,13 @@ "tier": 2.0, "currency": "USDT", "minNotional": 5000.0, - "maxNotional": 25000.0, + "maxNotional": 50000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 10.0, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "25000", + "notionalCap": "50000", "notionalFloor": "5000", "maintMarginRatio": "0.025", "cum": "25.0" @@ -18213,39 +18457,39 @@ { "tier": 3.0, "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, + "minNotional": 50000.0, + "maxNotional": 200000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 8.0, "info": { "bracket": "3", "initialLeverage": "8", - "notionalCap": "100000", - "notionalFloor": "25000", + "notionalCap": "200000", + "notionalFloor": "50000", "maintMarginRatio": "0.05", - "cum": "650.0" + "cum": "1275.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, + "minNotional": 200000.0, + "maxNotional": 500000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "notionalCap": "500000", + "notionalFloor": "200000", "maintMarginRatio": "0.1", - "cum": "5650.0" + "cum": "11275.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 250000.0, + "minNotional": 500000.0, "maxNotional": 1000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 2.0, @@ -18253,9 +18497,9 @@ "bracket": "5", "initialLeverage": "2", "notionalCap": "1000000", - "notionalFloor": "250000", + "notionalFloor": "500000", "maintMarginRatio": "0.125", - "cum": "11900.0" + "cum": "23775.0" } }, { @@ -18271,7 +18515,7 @@ "notionalCap": "3000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", - "cum": "386900.0" + "cum": "398775.0" } } ], @@ -18834,13 +19078,13 @@ "tier": 3.0, "currency": "USDT", "minNotional": 50000.0, - "maxNotional": 400000.0, + "maxNotional": 600000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "3", "initialLeverage": "20", - "notionalCap": "400000", + "notionalCap": "600000", "notionalFloor": "50000", "maintMarginRatio": "0.025", "cum": "770.0" @@ -18849,39 +19093,39 @@ { "tier": 4.0, "currency": "USDT", - "minNotional": 400000.0, - "maxNotional": 800000.0, + "minNotional": 600000.0, + "maxNotional": 1200000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "800000", - "notionalFloor": "400000", + "notionalCap": "1200000", + "notionalFloor": "600000", "maintMarginRatio": "0.05", - "cum": "10770.0" + "cum": "15770.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 800000.0, - "maxNotional": 2000000.0, + "minNotional": 1200000.0, + "maxNotional": 3000000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "800000", + "notionalCap": "3000000", + "notionalFloor": "1200000", "maintMarginRatio": "0.1", - "cum": "50770.0" + "cum": "75770.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 2000000.0, + "minNotional": 3000000.0, "maxNotional": 5000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, @@ -18889,9 +19133,9 @@ "bracket": "6", "initialLeverage": "4", "notionalCap": "5000000", - "notionalFloor": "2000000", + "notionalFloor": "3000000", "maintMarginRatio": "0.125", - "cum": "100770.0" + "cum": "150770.0" } }, { @@ -18907,7 +19151,7 @@ "notionalCap": "12000000", "notionalFloor": "5000000", "maintMarginRatio": "0.25", - "cum": "725770.0" + "cum": "775770.0" } }, { @@ -18923,7 +19167,7 @@ "notionalCap": "20000000", "notionalFloor": "12000000", "maintMarginRatio": "0.5", - "cum": "3725770.0" + "cum": "3775770.0" } } ], @@ -22404,13 +22648,13 @@ "tier": 3.0, "currency": "USDT", "minNotional": 50000.0, - "maxNotional": 300000.0, + "maxNotional": 450000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "3", "initialLeverage": "20", - "notionalCap": "300000", + "notionalCap": "450000", "notionalFloor": "50000", "maintMarginRatio": "0.025", "cum": "300.0" @@ -22419,55 +22663,55 @@ { "tier": 4.0, "currency": "USDT", - "minNotional": 300000.0, - "maxNotional": 600000.0, + "minNotional": 450000.0, + "maxNotional": 900000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "600000", - "notionalFloor": "300000", + "notionalCap": "900000", + "notionalFloor": "450000", "maintMarginRatio": "0.05", - "cum": "7800.0" + "cum": "11550.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 600000.0, - "maxNotional": 1600000.0, + "minNotional": 900000.0, + "maxNotional": 2400000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "1600000", - "notionalFloor": "600000", + "notionalCap": "2400000", + "notionalFloor": "900000", "maintMarginRatio": "0.1", - "cum": "37800.0" + "cum": "56550.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 1600000.0, - "maxNotional": 2000000.0, + "minNotional": 2400000.0, + "maxNotional": 3000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "2000000", - "notionalFloor": "1600000", + "notionalCap": "3000000", + "notionalFloor": "2400000", "maintMarginRatio": "0.125", - "cum": "77800.0" + "cum": "116550.0" } }, { "tier": 7.0, "currency": "USDT", - "minNotional": 2000000.0, + "minNotional": 3000000.0, "maxNotional": 6000000.0, "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, @@ -22475,9 +22719,9 @@ "bracket": "7", "initialLeverage": "2", "notionalCap": "6000000", - "notionalFloor": "2000000", + "notionalFloor": "3000000", "maintMarginRatio": "0.25", - "cum": "327800.0" + "cum": "491550.0" } }, { @@ -22493,7 +22737,7 @@ "notionalCap": "10000000", "notionalFloor": "6000000", "maintMarginRatio": "0.5", - "cum": "1827800.0" + "cum": "1991550.0" } } ], @@ -22618,10 +22862,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 15.0, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "15", + "initialLeverage": "25", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.02", @@ -22634,10 +22878,10 @@ "minNotional": 5000.0, "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 10.0, + "maxLeverage": 20.0, "info": { "bracket": "2", - "initialLeverage": "10", + "initialLeverage": "20", "notionalCap": "25000", "notionalFloor": "5000", "maintMarginRatio": "0.025", @@ -22650,10 +22894,10 @@ "minNotional": 25000.0, "maxNotional": 600000.0, "maintenanceMarginRate": 0.05, - "maxLeverage": 8.0, + "maxLeverage": 10.0, "info": { "bracket": "3", - "initialLeverage": "8", + "initialLeverage": "10", "notionalCap": "600000", "notionalFloor": "25000", "maintMarginRatio": "0.05", @@ -23186,13 +23430,13 @@ "tier": 2.0, "currency": "USDT", "minNotional": 5000.0, - "maxNotional": 25000.0, + "maxNotional": 50000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", + "notionalCap": "50000", "notionalFloor": "5000", "maintMarginRatio": "0.025", "cum": "25.0" @@ -23201,23 +23445,23 @@ { "tier": 3.0, "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 480000.0, + "minNotional": 50000.0, + "maxNotional": 600000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "480000", - "notionalFloor": "25000", + "notionalCap": "600000", + "notionalFloor": "50000", "maintMarginRatio": "0.05", - "cum": "650.0" + "cum": "1275.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 480000.0, + "minNotional": 600000.0, "maxNotional": 1280000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, @@ -23225,9 +23469,9 @@ "bracket": "4", "initialLeverage": "5", "notionalCap": "1280000", - "notionalFloor": "480000", + "notionalFloor": "600000", "maintMarginRatio": "0.1", - "cum": "24650.0" + "cum": "31275.0" } }, { @@ -23243,7 +23487,7 @@ "notionalCap": "1600000", "notionalFloor": "1280000", "maintMarginRatio": "0.125", - "cum": "56650.0" + "cum": "63275.0" } }, { @@ -23259,7 +23503,7 @@ "notionalCap": "4800000", "notionalFloor": "1600000", "maintMarginRatio": "0.25", - "cum": "256650.0" + "cum": "263275.0" } }, { @@ -23275,7 +23519,7 @@ "notionalCap": "8000000", "notionalFloor": "4800000", "maintMarginRatio": "0.5", - "cum": "1456650.0" + "cum": "1463275.0" } } ], @@ -24198,10 +24442,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.006, - "maxLeverage": 30.0, + "maxLeverage": 50.0, "info": { "bracket": "1", - "initialLeverage": "30", + "initialLeverage": "50", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.006", @@ -24228,13 +24472,13 @@ "tier": 3.0, "currency": "USDT", "minNotional": 50000.0, - "maxNotional": 600000.0, + "maxNotional": 900000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "3", "initialLeverage": "20", - "notionalCap": "600000", + "notionalCap": "900000", "notionalFloor": "50000", "maintMarginRatio": "0.025", "cum": "770.0" @@ -24243,81 +24487,81 @@ { "tier": 4.0, "currency": "USDT", - "minNotional": 600000.0, - "maxNotional": 1200000.0, + "minNotional": 900000.0, + "maxNotional": 1800000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1200000", - "notionalFloor": "600000", + "notionalCap": "1800000", + "notionalFloor": "900000", "maintMarginRatio": "0.05", - "cum": "15770.0" + "cum": "23270.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 1200000.0, - "maxNotional": 3200000.0, + "minNotional": 1800000.0, + "maxNotional": 4800000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "3200000", - "notionalFloor": "1200000", + "notionalCap": "4800000", + "notionalFloor": "1800000", "maintMarginRatio": "0.1", - "cum": "75770.0" + "cum": "113270.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 3200000.0, - "maxNotional": 5000000.0, + "minNotional": 4800000.0, + "maxNotional": 6000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "3200000", + "notionalCap": "6000000", + "notionalFloor": "4800000", "maintMarginRatio": "0.125", - "cum": "155770.0" + "cum": "233270.0" } }, { "tier": 7.0, "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 12000000.0, + "minNotional": 6000000.0, + "maxNotional": 18000000.0, "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, "info": { "bracket": "7", "initialLeverage": "2", - "notionalCap": "12000000", - "notionalFloor": "5000000", + "notionalCap": "18000000", + "notionalFloor": "6000000", "maintMarginRatio": "0.25", - "cum": "780770.0" + "cum": "983270.0" } }, { "tier": 8.0, "currency": "USDT", - "minNotional": 12000000.0, - "maxNotional": 20000000.0, + "minNotional": 18000000.0, + "maxNotional": 30000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "8", "initialLeverage": "1", - "notionalCap": "20000000", - "notionalFloor": "12000000", + "notionalCap": "30000000", + "notionalFloor": "18000000", "maintMarginRatio": "0.5", - "cum": "3780770.0" + "cum": "5483270.0" } } ], @@ -24570,13 +24814,13 @@ "tier": 2.0, "currency": "USDT", "minNotional": 5000.0, - "maxNotional": 25000.0, + "maxNotional": 50000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", + "notionalCap": "50000", "notionalFloor": "5000", "maintMarginRatio": "0.025", "cum": "25.0" @@ -24585,39 +24829,39 @@ { "tier": 3.0, "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 200000.0, + "minNotional": 50000.0, + "maxNotional": 300000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "200000", - "notionalFloor": "25000", + "notionalCap": "300000", + "notionalFloor": "50000", "maintMarginRatio": "0.05", - "cum": "650.0" + "cum": "1275.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 200000.0, - "maxNotional": 500000.0, + "minNotional": 300000.0, + "maxNotional": 800000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "200000", + "notionalCap": "800000", + "notionalFloor": "300000", "maintMarginRatio": "0.1", - "cum": "10650.0" + "cum": "16275.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 500000.0, + "minNotional": 800000.0, "maxNotional": 1000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, @@ -24625,9 +24869,9 @@ "bracket": "5", "initialLeverage": "4", "notionalCap": "1000000", - "notionalFloor": "500000", + "notionalFloor": "800000", "maintMarginRatio": "0.125", - "cum": "23150.0" + "cum": "36275.0" } }, { @@ -24643,7 +24887,7 @@ "notionalCap": "3000000", "notionalFloor": "1000000", "maintMarginRatio": "0.25", - "cum": "148150.0" + "cum": "161275.0" } }, { @@ -24659,7 +24903,7 @@ "notionalCap": "5000000", "notionalFloor": "3000000", "maintMarginRatio": "0.5", - "cum": "898150.0" + "cum": "911275.0" } } ], @@ -25254,13 +25498,13 @@ "tier": 4.0, "currency": "USDT", "minNotional": 50000.0, - "maxNotional": 250000.0, + "maxNotional": 500000.0, "maintenanceMarginRate": 0.02, "maxLeverage": 25.0, "info": { "bracket": "4", "initialLeverage": "25", - "notionalCap": "250000", + "notionalCap": "500000", "notionalFloor": "50000", "maintMarginRatio": "0.02", "cum": "545.0" @@ -25269,39 +25513,39 @@ { "tier": 5.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, + "minNotional": 500000.0, + "maxNotional": 2000000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "5", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "notionalCap": "2000000", + "notionalFloor": "500000", "maintMarginRatio": "0.05", - "cum": "8045.0" + "cum": "15545.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 5000000.0, + "minNotional": 2000000.0, + "maxNotional": 8000000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "5000000", - "notionalFloor": "1000000", + "notionalCap": "8000000", + "notionalFloor": "2000000", "maintMarginRatio": "0.1", - "cum": "58045.0" + "cum": "115545.0" } }, { "tier": 7.0, "currency": "USDT", - "minNotional": 5000000.0, + "minNotional": 8000000.0, "maxNotional": 10000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, @@ -25309,9 +25553,9 @@ "bracket": "7", "initialLeverage": "4", "notionalCap": "10000000", - "notionalFloor": "5000000", + "notionalFloor": "8000000", "maintMarginRatio": "0.125", - "cum": "183045.0" + "cum": "315545.0" } }, { @@ -25327,7 +25571,7 @@ "notionalCap": "20000000", "notionalFloor": "10000000", "maintMarginRatio": "0.15", - "cum": "433045.0" + "cum": "565545.0" } }, { @@ -25343,7 +25587,7 @@ "notionalCap": "30000000", "notionalFloor": "20000000", "maintMarginRatio": "0.25", - "cum": "2433045.0" + "cum": "2565545.0" } }, { @@ -25359,7 +25603,7 @@ "notionalCap": "50000000", "notionalFloor": "30000000", "maintMarginRatio": "0.5", - "cum": "9933045.0" + "cum": "1.0065545E7" } } ], From c9bbeedd88198bb43d3bb4e7b60e8b16dbf21d73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 03:56:37 +0000 Subject: [PATCH 38/48] Bump fastapi from 0.95.2 to 0.96.0 Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.95.2 to 0.96.0. - [Release notes](https://github.com/tiangolo/fastapi/releases) - [Commits](https://github.com/tiangolo/fastapi/compare/0.95.2...0.96.0) --- updated-dependencies: - dependency-name: fastapi dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b25e28046..facd7e561 100644 --- a/requirements.txt +++ b/requirements.txt @@ -38,7 +38,7 @@ orjson==3.8.14 sdnotify==0.3.2 # API Server -fastapi==0.95.2 +fastapi==0.96.0 pydantic==1.10.8 uvicorn==0.22.0 pyjwt==2.7.0 From 9dcab313b5d717d2b74e3f54dd1a162494bab586 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 03:56:40 +0000 Subject: [PATCH 39/48] Bump rich from 13.3.5 to 13.4.1 Bumps [rich](https://github.com/Textualize/rich) from 13.3.5 to 13.4.1. - [Release notes](https://github.com/Textualize/rich/releases) - [Changelog](https://github.com/Textualize/rich/blob/master/CHANGELOG.md) - [Commits](https://github.com/Textualize/rich/compare/v13.3.5...v13.4.1) --- updated-dependencies: - dependency-name: rich dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b25e28046..a0846d852 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,7 +23,7 @@ jinja2==3.1.2 tables==3.8.0 blosc==1.11.1 joblib==1.2.0 -rich==13.3.5 +rich==13.4.1 pyarrow==12.0.0; platform_machine != 'armv7l' # find first, C search in arrays From bdaf230bd1766c75f8cb6456b9a4a1e6ceb6cabb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 03:56:45 +0000 Subject: [PATCH 40/48] Bump orjson from 3.8.14 to 3.9.0 Bumps [orjson](https://github.com/ijl/orjson) from 3.8.14 to 3.9.0. - [Release notes](https://github.com/ijl/orjson/releases) - [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md) - [Commits](https://github.com/ijl/orjson/compare/3.8.14...3.9.0) --- updated-dependencies: - dependency-name: orjson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b25e28046..82bcd8ee1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,7 +32,7 @@ py_find_1st==1.1.5 # Load ticker files 30% faster python-rapidjson==1.10 # Properly format api responses -orjson==3.8.14 +orjson==3.9.0 # Notify systemd sdnotify==0.3.2 From 093181e8f2b21e122d67cf05fb17f7c2df79ab23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 03:57:15 +0000 Subject: [PATCH 41/48] Bump pandas from 2.0.1 to 2.0.2 Bumps [pandas](https://github.com/pandas-dev/pandas) from 2.0.1 to 2.0.2. - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Commits](https://github.com/pandas-dev/pandas/compare/v2.0.1...v2.0.2) --- updated-dependencies: - dependency-name: pandas dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b25e28046..81bee4977 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ numpy==1.24.3 -pandas==2.0.1 +pandas==2.0.2 pandas-ta==0.3.14b ccxt==3.1.13 From c2125698a720c30a95e6c22093be0897f69307e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 03:57:22 +0000 Subject: [PATCH 42/48] Bump types-requests from 2.31.0.0 to 2.31.0.1 Bumps [types-requests](https://github.com/python/typeshed) from 2.31.0.0 to 2.31.0.1. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 96d06ccbf..5822dd595 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -25,6 +25,6 @@ nbconvert==7.4.0 # mypy types types-cachetools==5.3.0.5 types-filelock==3.2.7 -types-requests==2.31.0.0 +types-requests==2.31.0.1 types-tabulate==0.9.0.2 types-python-dateutil==2.8.19.13 From e61659a2bcbb1e5855eda0eed5856516668eb0d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 03:57:43 +0000 Subject: [PATCH 43/48] Bump mkdocs-material from 9.1.14 to 9.1.15 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.14 to 9.1.15. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.1.14...9.1.15) --- updated-dependencies: - dependency-name: mkdocs-material dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index c5e478c78..6c77736f4 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,6 +1,6 @@ markdown==3.3.7 mkdocs==1.4.3 -mkdocs-material==9.1.14 +mkdocs-material==9.1.15 mdx_truly_sane_lists==1.3 pymdown-extensions==10.0.1 jinja2==3.1.2 From 4dcb6395ef92d9830d693747cd65792bfd747ff6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Jun 2023 07:13:09 +0200 Subject: [PATCH 44/48] Bump pre-commit requests types --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 67e7ece19..fc7648cd8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: additional_dependencies: - types-cachetools==5.3.0.5 - types-filelock==3.2.7 - - types-requests==2.31.0.0 + - types-requests==2.31.0.1 - types-tabulate==0.9.0.2 - types-python-dateutil==2.8.19.13 - SQLAlchemy==2.0.15 From 6ec91d11ae4cff646f66adfb6d9ce57a3740f35d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 07:40:33 +0000 Subject: [PATCH 45/48] Bump ccxt from 3.1.13 to 3.1.23 Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.1.13 to 3.1.23. - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/3.1.13...3.1.23) --- updated-dependencies: - dependency-name: ccxt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bdaf56d57..118ad95e2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.24.3 pandas==2.0.2 pandas-ta==0.3.14b -ccxt==3.1.13 +ccxt==3.1.23 cryptography==41.0.1; platform_machine != 'armv7l' cryptography==40.0.1; platform_machine == 'armv7l' aiohttp==3.8.4 From 21172802decab806f601375facce8a381af66eb2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Jun 2023 20:30:46 +0200 Subject: [PATCH 46/48] Devcontainer image should contain as many dependencies as possible --- .devcontainer/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 6389a50df..748efc4d9 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,11 +1,12 @@ -FROM freqtradeorg/freqtrade:develop +FROM freqtradeorg/freqtrade:develop_freqairl USER root # Install dependencies COPY requirements-dev.txt /freqtrade/ RUN apt-get update \ - && apt-get -y install git mercurial sudo vim build-essential \ + && apt-get -y install --no-install-recommends apt-utils dialog \ + && apt-get -y install --no-install-recommends git sudo vim build-essential \ && apt-get clean \ && mkdir -p /home/ftuser/.vscode-server /home/ftuser/.vscode-server-insiders /home/ftuser/commandhistory \ && echo "export PROMPT_COMMAND='history -a'" >> /home/ftuser/.bashrc \ From c269eef77e2675c32d1dee56873651e13ffe9f13 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Jun 2023 20:19:10 +0200 Subject: [PATCH 47/48] Remove unnecessary calc_profit_ratio call --- freqtrade/strategy/interface.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 80093fed8..dfdfd31d8 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -1085,6 +1085,11 @@ class IStrategy(ABC, HyperStrategyMixin): exits: List[ExitCheckTuple] = [] current_rate = rate current_profit = trade.calc_profit_ratio(current_rate) + current_profit_best = current_profit + if low is not None or high is not None: + # Set current rate to high for backtesting ROI exits + current_rate_best = (low if trade.is_short else high) or rate + current_profit_best = trade.calc_profit_ratio(current_rate_best) trade.adjust_min_max_rates(high or current_rate, low or current_rate) @@ -1093,20 +1098,13 @@ class IStrategy(ABC, HyperStrategyMixin): current_profit=current_profit, force_stoploss=force_stoploss, low=low, high=high) - # Set current rate to high for backtesting exits - current_rate = (low if trade.is_short else high) or rate - current_profit = trade.calc_profit_ratio(current_rate) - # if enter signal and ignore_roi is set, we don't need to evaluate min_roi. roi_reached = (not (enter and self.ignore_roi_if_entry_signal) - and self.min_roi_reached(trade=trade, current_profit=current_profit, + and self.min_roi_reached(trade=trade, current_profit=current_profit_best, current_time=current_time)) exit_signal = ExitType.NONE custom_reason = '' - # use provided rate in backtesting, not high/low. - current_rate = rate - current_profit = trade.calc_profit_ratio(current_rate) if self.use_exit_signal: if exit_ and not enter: From 0b8ef1b8801f3b5fda94f0472e7dd002548226b1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Jun 2023 21:13:52 +0200 Subject: [PATCH 48/48] Fix devcontainer invalid key --- .devcontainer/devcontainer.json | 35 +++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8fb643e8f..08b8240b9 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -19,23 +19,24 @@ "postCreateCommand": "freqtrade create-userdir --userdir user_data/", "workspaceFolder": "/workspaces/freqtrade", - - "settings": { - "terminal.integrated.shell.linux": "/bin/bash", - "editor.insertSpaces": true, - "files.trimTrailingWhitespace": true, - "[markdown]": { - "files.trimTrailingWhitespace": false, + "customizations": { + "settings": { + "terminal.integrated.shell.linux": "/bin/bash", + "editor.insertSpaces": true, + "files.trimTrailingWhitespace": true, + "[markdown]": { + "files.trimTrailingWhitespace": false, + }, + "python.pythonPath": "/usr/local/bin/python", }, - "python.pythonPath": "/usr/local/bin/python", - }, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-python.python", - "ms-python.vscode-pylance", - "davidanson.vscode-markdownlint", - "ms-azuretools.vscode-docker", - "vscode-icons-team.vscode-icons", - ], + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance", + "davidanson.vscode-markdownlint", + "ms-azuretools.vscode-docker", + "vscode-icons-team.vscode-icons", + ], + } }