From e8803477dfa269f9f95932f169c95554e22b504f Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Tue, 3 May 2022 22:56:55 -0600 Subject: [PATCH 001/220] exchange/exchange add param taker_or_maker to add_dry_order_fee --- freqtrade/exchange/exchange.py | 44 ++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 08bdab265..f0ff7e514 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -785,6 +785,26 @@ class Exchange: # Dry-run methods + def taker_or_maker( + self, + order_reason: Literal['entry', 'exit', 'stoploss'], # TODO: stoploss + ): + order_type = self._config['order_types'][order_reason] + if order_type == 'market' or order_reason == 'stoploss': + return 'taker' + else: + return ( + 'maker' if ( + ( + order_reason == 'entry' and + self._config['entry_pricing']['price_side'] == 'same' + ) or ( + order_reason == 'exit' and + self._config['exit_pricing']['price_side'] == 'same' + ) + ) else 'taker' + ) + def create_dry_run_order(self, pair: str, ordertype: str, side: str, amount: float, rate: float, leverage: float, params: Dict = {}, stop_loss: bool = False) -> Dict[str, Any]: @@ -824,7 +844,7 @@ class Exchange: 'filled': _amount, 'cost': (dry_order['amount'] * average) / leverage }) - dry_order = self.add_dry_order_fee(pair, dry_order) + dry_order = self.add_dry_order_fee(pair, dry_order, self.taker_or_maker('entry')) dry_order = self.check_dry_limit_order_filled(dry_order) @@ -832,12 +852,17 @@ class Exchange: # Copy order and close it - so the returned order is open unless it's a market order return dry_order - def add_dry_order_fee(self, pair: str, dry_order: Dict[str, Any]) -> Dict[str, Any]: + def add_dry_order_fee( + self, + pair: str, + dry_order: Dict[str, Any], + taker_or_maker: Literal['taker', 'maker'], + ) -> Dict[str, Any]: dry_order.update({ 'fee': { 'currency': self.get_pair_quote_currency(pair), - 'cost': dry_order['cost'] * self.get_fee(pair), - 'rate': self.get_fee(pair) + 'cost': dry_order['cost'] * self.get_fee(pair, taker_or_maker=taker_or_maker), + 'rate': self.get_fee(pair, taker_or_maker=taker_or_maker) } }) return dry_order @@ -917,7 +942,16 @@ class Exchange: 'filled': order['amount'], 'remaining': 0, }) - self.add_dry_order_fee(pair, order) + enter_long = not order['is_short'] and order['side'] == 'buy' + enter_short = order['is_short'] and order['side'] == 'sell' + entry_or_exit: Literal['entry', 'exit'] = ( + 'entry' if (enter_short or enter_long) else 'exit' + ) + self.add_dry_order_fee( + pair, + order, + self.taker_or_maker(entry_or_exit) + ) return order From 5d9aee6b7e6591ddb1953159223af8ebbb9cf6a1 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Tue, 3 May 2022 23:18:13 -0600 Subject: [PATCH 002/220] test_taker_or_maker --- tests/exchange/test_exchange.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 1368bcb85..3edb5187c 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -4957,3 +4957,24 @@ def test_stoploss_contract_size(mocker, default_conf, contract_size, order_amoun assert order['cost'] == 100 assert order['filled'] == 100 assert order['remaining'] == 100 + + +@pytest.mark.parametrize('order_reason,price_side,order_type,taker_or_maker', [ + ("entry", "same", "limit", "maker"), + ("exit", "same", "limit", "maker"), + ("entry", "other", "limit", "taker"), + ("exit", "other", "limit", "taker"), + ("entry", "same", "market", "maker"), + ("exit", "same", "market", "maker"), + ("entry", "other", "market", "taker"), + ("exit", "other", "market", "taker"), + ("stoploss", "same", "limit", "taker"), + ("stoploss", "same", "market", "taker"), + ("stoploss", "other", "limit", "taker"), + ("stoploss", "other", "market", "taker"), +]) +def test_taker_or_maker(mocker, default_conf, order_reason, price_side, order_type, taker_or_maker): + default_conf[f"{order_reason}_pricing"]["price_side"] = price_side + default_conf["order_types"][order_reason] = order_type + exchange = get_patched_exchange(mocker, default_conf) + assert exchange.taker_or_maker(order_reason) == taker_or_maker From dac9931b4a53aedeb4435483dcbb956203bb5530 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Tue, 3 May 2022 23:52:01 -0600 Subject: [PATCH 003/220] test_create_dry_run_order_fees --- tests/exchange/test_exchange.py | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 3edb5187c..ab51362a5 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1125,6 +1125,47 @@ def test_create_dry_run_order(default_conf, mocker, side, exchange_name, leverag assert order["cost"] == 1 * 200 / leverage +@pytest.mark.parametrize('side,is_short,order_reason', [ + ("buy", False, "entry"), + ("sell", False, "exit"), + ("buy", True, "exit"), + ("sell", True, "entry"), +]) +@pytest.mark.parametrize("order_type,price_side,fee", [ + ("limit", "same", 1.0), + ("limit", "other", 2.0), + ("market", "same", 2.0), + ("market", "other", 2.0), +]) +def test_create_dry_run_order_fees( + default_conf, + mocker, + side, + order_type, + is_short, + order_reason, + price_side, + fee, +): + default_conf[f"{order_reason}_pricing"]["price_side"] = "same" + default_conf["order_types"][order_reason] = order_type + mocker.patch( + 'freqtrade.exchange.Exchange.get_fee', + lambda symbol, taker_or_maker: 2.0 if taker_or_maker == 'taker' else 1.0 + ) + exchange = get_patched_exchange(mocker, default_conf) + + order = exchange.create_dry_run_order( + pair='ADA/USDT', + ordertype=order_type, + side=side, + amount=10, + rate=2.0, + ) + + assert order['ft_fee_base'] == fee + + @pytest.mark.parametrize("side,startprice,endprice", [ ("buy", 25.563, 25.566), ("sell", 25.566, 25.563) From 86ad5dd02a7ae680a1d566f7b83b55e5cf65f399 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Wed, 4 May 2022 00:08:41 -0600 Subject: [PATCH 004/220] test_exchange::test_taker_or_maker fixes --- tests/exchange/test_exchange.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index ab51362a5..a13dca4b6 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -5015,7 +5015,9 @@ def test_stoploss_contract_size(mocker, default_conf, contract_size, order_amoun ("stoploss", "other", "market", "taker"), ]) def test_taker_or_maker(mocker, default_conf, order_reason, price_side, order_type, taker_or_maker): - default_conf[f"{order_reason}_pricing"]["price_side"] = price_side + if order_reason != 'stoploss': + default_conf[f"{order_reason}_pricing"]["price_side"] = price_side + default_conf["order_types"] = {} default_conf["order_types"][order_reason] = order_type exchange = get_patched_exchange(mocker, default_conf) assert exchange.taker_or_maker(order_reason) == taker_or_maker From 10cbb5e67c32b184445f868366e4eef38afe5878 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Wed, 4 May 2022 00:10:09 -0600 Subject: [PATCH 005/220] test_exchange::test_taker_or_maker fixes --- tests/exchange/test_exchange.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index a13dca4b6..86928a2f6 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -5005,13 +5005,13 @@ def test_stoploss_contract_size(mocker, default_conf, contract_size, order_amoun ("exit", "same", "limit", "maker"), ("entry", "other", "limit", "taker"), ("exit", "other", "limit", "taker"), - ("entry", "same", "market", "maker"), - ("exit", "same", "market", "maker"), + ("stoploss", "same", "limit", "taker"), + ("stoploss", "other", "limit", "taker"), + ("entry", "same", "market", "taker"), + ("exit", "same", "market", "taker"), ("entry", "other", "market", "taker"), ("exit", "other", "market", "taker"), - ("stoploss", "same", "limit", "taker"), ("stoploss", "same", "market", "taker"), - ("stoploss", "other", "limit", "taker"), ("stoploss", "other", "market", "taker"), ]) def test_taker_or_maker(mocker, default_conf, order_reason, price_side, order_type, taker_or_maker): From 2b61aa282a434f4011fbd5e5720270b4f6eefe35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=AE=AE=E0=AE=A9=E0=AF=8B=E0=AE=9C=E0=AF=8D=E0=AE=95?= =?UTF-8?q?=E0=AF=81=E0=AE=AE=E0=AE=BE=E0=AE=B0=E0=AF=8D=20=E0=AE=AA?= =?UTF-8?q?=E0=AE=B4=E0=AE=A9=E0=AE=BF=E0=AE=9A=E0=AF=8D=E0=AE=9A=E0=AE=BE?= =?UTF-8?q?=E0=AE=AE=E0=AE=BF?= Date: Wed, 18 May 2022 03:41:10 +0530 Subject: [PATCH 006/220] Removed None in dict.get() https://stackoverflow.com/a/12631641 Extra Changes: freqtrade\freqtradebot.py:70 freqtrade\plugins\pairlistmanager.py:31 --- freqtrade/commands/hyperopt_commands.py | 2 +- freqtrade/configuration/configuration.py | 8 ++++---- freqtrade/exchange/exchange.py | 12 ++++++------ freqtrade/freqtradebot.py | 14 +++++++------- freqtrade/optimize/backtesting.py | 4 ++-- freqtrade/optimize/hyperopt.py | 2 +- freqtrade/optimize/hyperopt_tools.py | 16 ++++++++-------- freqtrade/plugins/pairlist/AgeFilter.py | 2 +- freqtrade/plugins/pairlist/PerformanceFilter.py | 2 +- freqtrade/plugins/pairlist/PriceFilter.py | 2 +- .../plugins/pairlist/rangestabilityfilter.py | 2 +- freqtrade/plugins/pairlistmanager.py | 2 +- freqtrade/rpc/api_server/api_v1.py | 2 +- freqtrade/rpc/rpc.py | 4 ++-- freqtrade/rpc/telegram.py | 6 +++--- freqtrade/rpc/webhook.py | 14 +++++++------- freqtrade/wallets.py | 6 +++--- 17 files changed, 50 insertions(+), 50 deletions(-) diff --git a/freqtrade/commands/hyperopt_commands.py b/freqtrade/commands/hyperopt_commands.py index 344828282..19e291ea7 100755 --- a/freqtrade/commands/hyperopt_commands.py +++ b/freqtrade/commands/hyperopt_commands.py @@ -24,7 +24,7 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None: print_colorized = config.get('print_colorized', False) print_json = config.get('print_json', False) - export_csv = config.get('export_csv', None) + export_csv = config.get('export_csv') no_details = config.get('hyperopt_list_no_details', False) no_header = False diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index 96b585cd1..e4c7b8f9d 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -127,7 +127,7 @@ class Configuration: # Default to in-memory db for dry_run if not specified config['db_url'] = constants.DEFAULT_DB_DRYRUN_URL else: - if not config.get('db_url', None): + if not config.get('db_url'): config['db_url'] = constants.DEFAULT_DB_PROD_URL logger.info('Dry run is disabled') @@ -180,7 +180,7 @@ class Configuration: config['user_data_dir'] = create_userdata_dir(config['user_data_dir'], create_dir=False) logger.info('Using user-data directory: %s ...', config['user_data_dir']) - config.update({'datadir': create_datadir(config, self.args.get('datadir', None))}) + config.update({'datadir': create_datadir(config, self.args.get('datadir'))}) logger.info('Using data directory: %s ...', config.get('datadir')) if self.args.get('exportfilename'): @@ -219,7 +219,7 @@ class Configuration: if config.get('max_open_trades') == -1: config['max_open_trades'] = float('inf') - if self.args.get('stake_amount', None): + if self.args.get('stake_amount'): # Convert explicitly to float to support CLI argument for both unlimited and value try: self.args['stake_amount'] = float(self.args['stake_amount']) @@ -459,7 +459,7 @@ class Configuration: configuration instead of the content) """ if (argname in self.args and self.args[argname] is not None - and self.args[argname] is not False): + and self.args[argname] is not False): config.update({argname: self.args[argname]}) if logfun: diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index d2766cd6d..685f86899 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -383,11 +383,11 @@ class Exchange: Ensures that Configured mode aligns to """ return ( - market.get('quote', None) is not None - and market.get('base', None) is not None + market.get('quote') is not None + and market.get('base') is not None and (self.precisionMode != TICK_SIZE # Too low precision will falsify calculations - or market.get('precision', {}).get('price', None) > 1e-11) + or market.get('precision', {}).get('price') > 1e-11) and ((self.trading_mode == TradingMode.SPOT and self.market_is_spot(market)) or (self.trading_mode == TradingMode.MARGIN and self.market_is_margin(market)) or (self.trading_mode == TradingMode.FUTURES and self.market_is_future(market))) @@ -537,7 +537,7 @@ class Exchange: # The internal info array is different for each particular market, # its contents depend on the exchange. # It can also be a string or similar ... so we need to verify that first. - elif (isinstance(self.markets[pair].get('info', None), dict) + elif (isinstance(self.markets[pair].get('info'), dict) and self.markets[pair].get('info', {}).get('prohibitedIn', False)): # Warn users about restricted pairs in whitelist. # We cannot determine reliably if Users are affected. @@ -1593,7 +1593,7 @@ class Exchange: def get_fee(self, symbol: str, type: str = '', side: str = '', amount: float = 1, price: float = 1, taker_or_maker: str = 'maker') -> float: try: - if self._config['dry_run'] and self._config.get('fee', None) is not None: + if self._config['dry_run'] and self._config.get('fee') is not None: return self._config['fee'] # validate that markets are loaded before trying to get fee if self._api.markets is None or len(self._api.markets) == 0: @@ -1654,7 +1654,7 @@ class Exchange: fee_to_quote_rate = safe_value_fallback2(tick, tick, 'last', 'ask') except ExchangeError: - fee_to_quote_rate = self._config['exchange'].get('unknown_fee_rate', None) + fee_to_quote_rate = self._config['exchange'].get('unknown_fee_rate') if not fee_to_quote_rate: return None return round((self._contracts_to_amount( diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 315db3ae6..cbd44a755 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -67,7 +67,7 @@ class FreqtradeBot(LoggingMixin): self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config) - init_db(self.config.get('db_url', None), clean_open_orders=self.config['dry_run']) + init_db(self.config['db_url'], clean_open_orders=self.config['dry_run']) self.wallets = Wallets(self.config, self.exchange) @@ -638,7 +638,7 @@ class FreqtradeBot(LoggingMixin): ) order_obj = Order.parse_from_ccxt_object(order, pair, side) order_id = order['id'] - order_status = order.get('status', None) + order_status = order.get('status') logger.info(f"Order #{order_id} was created for {pair} and status is {order_status}.") # we assume the order is executed at the price requested @@ -845,7 +845,7 @@ class FreqtradeBot(LoggingMixin): 'order_type': order_type, 'stake_amount': trade.stake_amount, 'stake_currency': self.config['stake_currency'], - 'fiat_currency': self.config.get('fiat_display_currency', None), + 'fiat_currency': self.config.get('fiat_display_currency'), 'amount': safe_value_fallback(order, 'filled', 'amount') or trade.amount, 'open_date': trade.open_date or datetime.utcnow(), 'current_rate': current_rate, @@ -874,7 +874,7 @@ class FreqtradeBot(LoggingMixin): 'order_type': order_type, 'stake_amount': trade.stake_amount, 'stake_currency': self.config['stake_currency'], - 'fiat_currency': self.config.get('fiat_display_currency', None), + 'fiat_currency': self.config.get('fiat_display_currency'), 'amount': trade.amount, 'open_date': trade.open_date, 'current_rate': current_rate, @@ -1529,7 +1529,7 @@ class FreqtradeBot(LoggingMixin): 'open_date': trade.open_date, 'close_date': trade.close_date or datetime.utcnow(), 'stake_currency': self.config['stake_currency'], - 'fiat_currency': self.config.get('fiat_display_currency', None), + 'fiat_currency': self.config.get('fiat_display_currency'), } if 'fiat_display_currency' in self.config: @@ -1578,7 +1578,7 @@ class FreqtradeBot(LoggingMixin): 'open_date': trade.open_date, 'close_date': trade.close_date or datetime.now(timezone.utc), 'stake_currency': self.config['stake_currency'], - 'fiat_currency': self.config.get('fiat_display_currency', None), + 'fiat_currency': self.config.get('fiat_display_currency'), 'reason': reason, } @@ -1640,7 +1640,7 @@ class FreqtradeBot(LoggingMixin): if order['status'] in constants.NON_OPEN_EXCHANGE_STATES: # If a entry order was closed, force update on stoploss on exchange - if order.get('side', None) == trade.entry_side: + if order.get('side') == trade.entry_side: trade = self.cancel_stoploss_on_exchange(trade) # TODO: Margin will need to use interest_rate as well. # interest_rate = self.exchange.get_interest_rate() diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 4e604898f..f1ccd3b51 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -87,7 +87,7 @@ class Backtesting: self.exchange = ExchangeResolver.load_exchange(self._exchange_name, self.config) self.dataprovider = DataProvider(self.config, self.exchange) - if self.config.get('strategy_list', None): + if self.config.get('strategy_list'): for strat in list(self.config['strategy_list']): stratconf = deepcopy(self.config) stratconf['strategy'] = strat @@ -123,7 +123,7 @@ class Backtesting: if len(self.pairlists.whitelist) == 0: raise OperationalException("No pair in whitelist.") - if config.get('fee', None) is not None: + if config.get('fee') is not None: self.fee = config['fee'] else: self.fee = self.exchange.get_fee(symbol=self.pairlists.whitelist[0]) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 1dafb483c..a267ca4ac 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -455,7 +455,7 @@ class Hyperopt: return self.opt.ask(n_points=n_points), [False for _ in range(n_points)] def start(self) -> None: - self.random_state = self._set_random_state(self.config.get('hyperopt_random_state', None)) + self.random_state = self._set_random_state(self.config.get('hyperopt_random_state')) logger.info(f"Using optimizer random state: {self.random_state}") self.hyperopt_table_header = -1 # Initialize spaces ... diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index 0421e6e38..ab6ef013b 100755 --- a/freqtrade/optimize/hyperopt_tools.py +++ b/freqtrade/optimize/hyperopt_tools.py @@ -127,14 +127,14 @@ class HyperoptTools(): 'only_profitable': config.get('hyperopt_list_profitable', False), 'filter_min_trades': config.get('hyperopt_list_min_trades', 0), 'filter_max_trades': config.get('hyperopt_list_max_trades', 0), - 'filter_min_avg_time': config.get('hyperopt_list_min_avg_time', None), - 'filter_max_avg_time': config.get('hyperopt_list_max_avg_time', None), - 'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit', None), - 'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit', None), - 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None), - 'filter_max_total_profit': config.get('hyperopt_list_max_total_profit', None), - 'filter_min_objective': config.get('hyperopt_list_min_objective', None), - 'filter_max_objective': config.get('hyperopt_list_max_objective', None), + 'filter_min_avg_time': config.get('hyperopt_list_min_avg_time'), + 'filter_max_avg_time': config.get('hyperopt_list_max_avg_time'), + 'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit'), + 'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit'), + 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit'), + 'filter_max_total_profit': config.get('hyperopt_list_max_total_profit'), + 'filter_min_objective': config.get('hyperopt_list_min_objective'), + 'filter_max_objective': config.get('hyperopt_list_max_objective'), } if not HyperoptTools._test_hyperopt_results_exist(results_file): # No file found. diff --git a/freqtrade/plugins/pairlist/AgeFilter.py b/freqtrade/plugins/pairlist/AgeFilter.py index 418c0f14e..786f32e88 100644 --- a/freqtrade/plugins/pairlist/AgeFilter.py +++ b/freqtrade/plugins/pairlist/AgeFilter.py @@ -30,7 +30,7 @@ class AgeFilter(IPairList): self._symbolsCheckFailed = PeriodicCache(maxsize=1000, ttl=86_400) self._min_days_listed = pairlistconfig.get('min_days_listed', 10) - self._max_days_listed = pairlistconfig.get('max_days_listed', None) + self._max_days_listed = pairlistconfig.get('max_days_listed') candle_limit = exchange.ohlcv_candle_limit('1d', self._config['candle_type_def']) if self._min_days_listed < 1: diff --git a/freqtrade/plugins/pairlist/PerformanceFilter.py b/freqtrade/plugins/pairlist/PerformanceFilter.py index 5b02a47ab..8e0b407c3 100644 --- a/freqtrade/plugins/pairlist/PerformanceFilter.py +++ b/freqtrade/plugins/pairlist/PerformanceFilter.py @@ -21,7 +21,7 @@ class PerformanceFilter(IPairList): super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos) self._minutes = pairlistconfig.get('minutes', 0) - self._min_profit = pairlistconfig.get('min_profit', None) + self._min_profit = pairlistconfig.get('min_profit') @property def needstickers(self) -> bool: diff --git a/freqtrade/plugins/pairlist/PriceFilter.py b/freqtrade/plugins/pairlist/PriceFilter.py index 009789eaf..4c5db52b1 100644 --- a/freqtrade/plugins/pairlist/PriceFilter.py +++ b/freqtrade/plugins/pairlist/PriceFilter.py @@ -70,7 +70,7 @@ class PriceFilter(IPairList): :param ticker: ticker dict as returned from ccxt.fetch_tickers() :return: True if the pair can stay, false if it should be removed """ - if ticker.get('last', None) is None or ticker.get('last') == 0: + if ticker.get('last') is None or ticker.get('last') == 0: self.log_once(f"Removed {pair} from whitelist, because " "ticker['last'] is empty (Usually no trade in the last 24h).", logger.info) diff --git a/freqtrade/plugins/pairlist/rangestabilityfilter.py b/freqtrade/plugins/pairlist/rangestabilityfilter.py index de016c3a6..f3e7bc0d6 100644 --- a/freqtrade/plugins/pairlist/rangestabilityfilter.py +++ b/freqtrade/plugins/pairlist/rangestabilityfilter.py @@ -27,7 +27,7 @@ class RangeStabilityFilter(IPairList): self._days = pairlistconfig.get('lookback_days', 10) self._min_rate_of_change = pairlistconfig.get('min_rate_of_change', 0.01) - self._max_rate_of_change = pairlistconfig.get('max_rate_of_change', None) + self._max_rate_of_change = pairlistconfig.get('max_rate_of_change') self._refresh_period = pairlistconfig.get('refresh_period', 1440) self._def_candletype = self._config['candle_type_def'] diff --git a/freqtrade/plugins/pairlistmanager.py b/freqtrade/plugins/pairlistmanager.py index 2ae67a157..3ddad4a5e 100644 --- a/freqtrade/plugins/pairlistmanager.py +++ b/freqtrade/plugins/pairlistmanager.py @@ -28,7 +28,7 @@ class PairListManager(LoggingMixin): self._blacklist = self._config['exchange'].get('pair_blacklist', []) self._pairlist_handlers: List[IPairList] = [] self._tickers_needed = False - for pairlist_handler_config in self._config.get('pairlists', None): + for pairlist_handler_config in self._config.get('pairlists', []): pairlist_handler = PairListResolver.load_pairlist( pairlist_handler_config['method'], exchange=exchange, diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index a8b9873d7..c8299a153 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -281,7 +281,7 @@ def get_strategy(strategy: str, config=Depends(get_config)): def list_available_pairs(timeframe: Optional[str] = None, stake_currency: Optional[str] = None, candletype: Optional[CandleType] = None, config=Depends(get_config)): - dh = get_datahandler(config['datadir'], config.get('dataformat_ohlcv', None)) + dh = get_datahandler(config['datadir'], config.get('dataformat_ohlcv')) trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT) pair_interval = dh.ohlcv_get_available_data(config['datadir'], trading_mode) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index a98e3f96d..4c03b8bd4 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -96,7 +96,7 @@ class RPC: """ self._freqtrade = freqtrade self._config: Dict[str, Any] = freqtrade.config - if self._config.get('fiat_display_currency', None): + if self._config.get('fiat_display_currency'): self._fiat_converter = CryptoToFiatConverter() @staticmethod @@ -600,7 +600,7 @@ class RPC: else: try: pair = self._freqtrade.exchange.get_valid_pair_combination(coin, stake_currency) - rate = tickers.get(pair, {}).get('last', None) + rate = tickers.get(pair, {}).get('last') if rate: if pair.startswith(stake_currency) and not pair.endswith(stake_currency): rate = 1.0 / rate diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index f26de8b5c..81fb206cc 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -241,7 +241,7 @@ class Telegram(RPCHandler): f" {entry_side['entered'] if is_fill else entry_side['enter']} {msg['pair']}" f" (#{msg['trade_id']})\n" ) - message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag', None) else "" + message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else "" message += f"*Amount:* `{msg['amount']:.8f}`\n" if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0: message += f"*Leverage:* `{msg['leverage']}`\n" @@ -254,7 +254,7 @@ class Telegram(RPCHandler): message += f"*Total:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}" - if msg.get('fiat_currency', None): + if msg.get('fiat_currency'): message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}" message += ")`" @@ -270,7 +270,7 @@ class Telegram(RPCHandler): msg['enter_tag'] = msg['enter_tag'] if "enter_tag" in msg.keys() else None msg['emoji'] = self._get_sell_emoji(msg) msg['leverage_text'] = (f"*Leverage:* `{msg['leverage']:.1f}`\n" - if msg.get('leverage', None) and msg.get('leverage', 1.0) != 1.0 + if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0 else "") # Check if all sell properties are available. diff --git a/freqtrade/rpc/webhook.py b/freqtrade/rpc/webhook.py index a2edcbc85..1b39a29b7 100644 --- a/freqtrade/rpc/webhook.py +++ b/freqtrade/rpc/webhook.py @@ -45,21 +45,21 @@ class Webhook(RPCHandler): try: whconfig = self._config['webhook'] if msg['type'] in [RPCMessageType.ENTRY]: - valuedict = whconfig.get('webhookentry', None) + valuedict = whconfig.get('webhookentry') elif msg['type'] in [RPCMessageType.ENTRY_CANCEL]: - valuedict = whconfig.get('webhookentrycancel', None) + valuedict = whconfig.get('webhookentrycancel') elif msg['type'] in [RPCMessageType.ENTRY_FILL]: - valuedict = whconfig.get('webhookentryfill', None) + valuedict = whconfig.get('webhookentryfill') elif msg['type'] == RPCMessageType.EXIT: - valuedict = whconfig.get('webhookexit', None) + valuedict = whconfig.get('webhookexit') elif msg['type'] == RPCMessageType.EXIT_FILL: - valuedict = whconfig.get('webhookexitfill', None) + valuedict = whconfig.get('webhookexitfill') elif msg['type'] == RPCMessageType.EXIT_CANCEL: - valuedict = whconfig.get('webhookexitcancel', None) + valuedict = whconfig.get('webhookexitcancel') elif msg['type'] in (RPCMessageType.STATUS, RPCMessageType.STARTUP, RPCMessageType.WARNING): - valuedict = whconfig.get('webhookstatus', None) + valuedict = whconfig.get('webhookstatus') else: raise NotImplementedError('Unknown message type: {}'.format(msg['type'])) if not valuedict: diff --git a/freqtrade/wallets.py b/freqtrade/wallets.py index 0c2197917..14e5a6743 100644 --- a/freqtrade/wallets.py +++ b/freqtrade/wallets.py @@ -131,9 +131,9 @@ class Wallets: if isinstance(balances[currency], dict): self._wallets[currency] = Wallet( currency, - balances[currency].get('free', None), - balances[currency].get('used', None), - balances[currency].get('total', None) + balances[currency].get('free'), + balances[currency].get('used'), + balances[currency].get('total') ) # Remove currencies no longer in get_balances output for currency in deepcopy(self._wallets): From cce8d1aa4d4f424d35a97c6f7cbb79a698dbd38b Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 31 May 2022 08:48:34 +0000 Subject: [PATCH 007/220] Update get_market_leverage_tiers to be async --- freqtrade/exchange/exchange.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index c1a9059a7..c292d7dcb 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -2131,10 +2131,11 @@ class Exchange: except ccxt.BaseError as e: raise OperationalException(e) from e - @retrier - def get_market_leverage_tiers(self, symbol) -> List[Dict]: + @retrier_async + async def get_market_leverage_tiers(self, symbol: str) -> Tuple[str, List[Dict]]: try: - return self._api.fetch_market_leverage_tiers(symbol) + tier = await self._api_async.fetch_market_leverage_tiers(symbol) + return symbol, tier except ccxt.DDoSProtection as e: raise DDosProtection(e) from e except (ccxt.NetworkError, ccxt.ExchangeError) as e: @@ -2168,8 +2169,14 @@ class Exchange: f"Initializing leverage_tiers for {len(symbols)} markets. " "This will take about a minute.") - for symbol in sorted(symbols): - tiers[symbol] = self.get_market_leverage_tiers(symbol) + coros = [self.get_market_leverage_tiers(symbol) for symbol in sorted(symbols)] + + for input_coro in chunks(coros, 100): + + results = self.loop.run_until_complete( + asyncio.gather(*input_coro, return_exceptions=True)) + for symbol, res in results: + tiers[symbol] = res logger.info(f"Done initializing {len(symbols)} markets.") From ea537b32c73f6ce0a0cd17c1630292a3f0bcb9c6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 31 May 2022 11:40:14 +0000 Subject: [PATCH 008/220] Update tests for leverage_tier_loading --- tests/conftest.py | 16 ++++++++++++++-- tests/exchange/test_okx.py | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 02738b0e9..c5c253891 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -78,9 +78,21 @@ def get_args(args): # Source: https://stackoverflow.com/questions/29881236/how-to-mock-asyncio-coroutines -def get_mock_coro(return_value): +# TODO: This should be replaced with AsyncMock once support for python 3.7 is dropped. +def get_mock_coro(return_value=None, side_effect=None): async def mock_coro(*args, **kwargs): - return return_value + if side_effect: + if isinstance(side_effect, list): + effect = side_effect.pop(0) + else: + effect = side_effect + if isinstance(effect, Exception): + raise effect + if callable(effect): + return effect(*args, **kwargs) + return effect + else: + return return_value return Mock(wraps=mock_coro) diff --git a/tests/exchange/test_okx.py b/tests/exchange/test_okx.py index 19c09ad9e..91c4a3368 100644 --- a/tests/exchange/test_okx.py +++ b/tests/exchange/test_okx.py @@ -6,7 +6,7 @@ import pytest from freqtrade.enums import MarginMode, TradingMode from freqtrade.enums.candletype import CandleType from freqtrade.exchange.exchange import timeframe_to_minutes -from tests.conftest import get_patched_exchange +from tests.conftest import get_mock_coro, get_patched_exchange from tests.exchange.test_exchange import ccxt_exceptionhandlers @@ -273,7 +273,7 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets): 'fetchLeverageTiers': False, 'fetchMarketLeverageTiers': True, }) - api_mock.fetch_market_leverage_tiers = MagicMock(side_effect=[ + api_mock.fetch_market_leverage_tiers = get_mock_coro(side_effect=[ [ { 'tier': 1, From 7fe8b7661d7cfe64129c78082622f8e4e9744599 Mon Sep 17 00:00:00 2001 From: Surfer Admin Date: Tue, 31 May 2022 15:46:43 -0400 Subject: [PATCH 009/220] Display the signal candle analyzed in telegram. --- freqtrade/freqtradebot.py | 20 ++++++++++++++++++++ freqtrade/rpc/telegram.py | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index fba63459b..a9e15d972 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -852,6 +852,16 @@ class FreqtradeBot(LoggingMixin): 'current_rate': current_rate, } + # display the candle analyzed in telegram + analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(trade.pair, + self.strategy.timeframe) + analyzed_candle = analyzed_df.iloc[-1] if len(analyzed_df) > 0 else None + if analyzed_candle is not None: + candle_columns = analyzed_candle[['date', 'open', 'high', 'low', 'close']] + msg.update({ + 'analyzed_candle': candle_columns.to_json(date_unit='s', date_format='iso') + }) + # Send the message self.rpc.send_msg(msg) @@ -1540,6 +1550,16 @@ class FreqtradeBot(LoggingMixin): 'fiat_currency': self.config['fiat_display_currency'], }) + # display the candle analyzed in telegram + analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(trade.pair, + self.strategy.timeframe) + analyzed_candle = analyzed_df.iloc[-1] if len(analyzed_df) > 0 else None + if analyzed_candle is not None: + candle_columns = analyzed_candle[['date', 'open', 'high', 'low', 'close']] + msg.update({ + 'analyzed_candle': candle_columns.to_json(date_unit='s', date_format='iso') + }) + # Send the message self.rpc.send_msg(msg) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 4a274002e..8364578a4 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -241,6 +241,8 @@ class Telegram(RPCHandler): f" {entry_side['entered'] if is_fill else entry_side['enter']} {msg['pair']}" f" (#{msg['trade_id']})\n" ) + if msg.get('analyzed_candle'): + message += f"*Analyzed Candle:* `{msg['analyzed_candle']}`\n" message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag', None) else "" message += f"*Amount:* `{msg['amount']:.8f}`\n" if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0: @@ -288,6 +290,12 @@ class Telegram(RPCHandler): message = ( f"{msg['emoji']} *{msg['exchange']}:* " f"{'Exited' if is_fill else 'Exiting'} {msg['pair']} (#{msg['trade_id']})\n" + ) + if not is_fill and msg.get('analyzed_candle'): + message += ( + f"*Analyzed Candle:* `{msg['analyzed_candle']}`\n" + ) + message += ( f"*{'Profit' if is_fill else 'Unrealized Profit'}:* " f"`{msg['profit_ratio']:.2%}{msg['profit_extra']}`\n" f"*Enter Tag:* `{msg['enter_tag']}`\n" From 0809f9aef69776805912bf8b32621a0a3d481959 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 18 Jun 2022 17:44:15 +0200 Subject: [PATCH 010/220] Add offset to trade response --- freqtrade/rpc/api_server/api_schemas.py | 1 + freqtrade/rpc/rpc.py | 1 + tests/rpc/test_rpc_apiserver.py | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index 7566e2ac0..333f2fe6e 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -283,6 +283,7 @@ class OpenTradeSchema(TradeSchema): class TradeResponse(BaseModel): trades: List[TradeSchema] trades_count: int + offset: int total_trades: int diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 31fe4c469..dbbb78c98 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -365,6 +365,7 @@ class RPC: return { "trades": output, "trades_count": len(output), + "offset": offset, "total_trades": Trade.get_trades([Trade.is_open.is_(False)]).count(), } diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index b0ff5e1b2..c0de54c6d 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -578,9 +578,10 @@ def test_api_trades(botclient, mocker, fee, markets, is_short): ) rc = client_get(client, f"{BASE_URI}/trades") assert_response(rc) - assert len(rc.json()) == 3 + assert len(rc.json()) == 4 assert rc.json()['trades_count'] == 0 assert rc.json()['total_trades'] == 0 + assert rc.json()['offset'] == 0 create_mock_trades(fee, is_short=is_short) Trade.query.session.flush() From 0d967f93baf69e08bda264df0702f4a433abf64b Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 19 Jun 2022 16:13:00 +0200 Subject: [PATCH 011/220] Improve performance of some RPC calls These don't need orders to be loaded. As a side-effect, this will also reduce the strain on the database. --- freqtrade/persistence/trade_model.py | 13 +++++++++---- freqtrade/rpc/rpc.py | 5 +++-- tests/test_persistence.py | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 39ebd75b4..0c8c985c8 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional from sqlalchemy import (Boolean, Column, DateTime, Enum, Float, ForeignKey, Integer, String, UniqueConstraint, desc, func) -from sqlalchemy.orm import Query, relationship +from sqlalchemy.orm import Query, lazyload, relationship from freqtrade.constants import DATETIME_PRINT_FORMAT, NON_OPEN_EXCHANGE_STATES, BuySell, LongShort from freqtrade.enums import ExitType, TradingMode @@ -1115,7 +1115,7 @@ class Trade(_DECL_BASE, LocalTrade): ) @staticmethod - def get_trades(trade_filter=None) -> Query: + def get_trades(trade_filter=None, include_orders: bool = True) -> Query: """ Helper function to query Trades using filters. NOTE: Not supported in Backtesting. @@ -1130,9 +1130,14 @@ class Trade(_DECL_BASE, LocalTrade): if trade_filter is not None: if not isinstance(trade_filter, list): trade_filter = [trade_filter] - return Trade.query.filter(*trade_filter) + this_query = Trade.query.filter(*trade_filter) else: - return Trade.query + this_query = Trade.query + if not include_orders: + # Don't load order relations + # Consider using noload or raiseload instead of lazyload + this_query = this_query.options(lazyload(Trade.orders)) + return this_query @staticmethod def get_open_order_trades() -> List['Trade']: diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index dbbb78c98..c42a6f683 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -380,7 +380,7 @@ class RPC: return 'losses' else: return 'draws' - trades: List[Trade] = Trade.get_trades([Trade.is_open.is_(False)]) + trades: List[Trade] = Trade.get_trades([Trade.is_open.is_(False)], include_orders=False) # Sell reason exit_reasons = {} for trade in trades: @@ -408,7 +408,8 @@ class RPC: """ Returns cumulative profit statistics """ trade_filter = ((Trade.is_open.is_(False) & (Trade.close_date >= start_date)) | Trade.is_open.is_(True)) - trades: List[Trade] = Trade.get_trades(trade_filter).order_by(Trade.id).all() + trades: List[Trade] = Trade.get_trades( + trade_filter, include_orders=False).order_by(Trade.id).all() profit_all_coin = [] profit_all_ratio = [] diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 357233dfa..deaad258b 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -2075,6 +2075,24 @@ def test_get_trades_proxy(fee, use_db, is_short): Trade.use_db = True +@pytest.mark.usefixtures("init_persistence") +@pytest.mark.parametrize('is_short', [True, False]) +def test_get_trades__query(fee, is_short): + query = Trade.get_trades([]) + # without orders there should be no join issued. + query1 = Trade.get_trades([], include_orders=False) + + assert "JOIN orders" in str(query) + assert "JOIN orders" not in str(query1) + + create_mock_trades(fee, is_short) + query = Trade.get_trades([]) + query1 = Trade.get_trades([], include_orders=False) + + assert "JOIN orders" in str(query) + assert "JOIN orders" not in str(query1) + + def test_get_trades_backtest(): Trade.use_db = False with pytest.raises(NotImplementedError, match=r"`Trade.get_trades\(\)` not .*"): From 8406010260e3d79be0638b375b63fd447d4711da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jun 2022 03:01:26 +0000 Subject: [PATCH 012/220] Bump types-cachetools from 5.0.1 to 5.0.2 Bumps [types-cachetools](https://github.com/python/typeshed) from 5.0.1 to 5.0.2. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-cachetools 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 19912d59c..53c85f176 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -22,7 +22,7 @@ time-machine==2.7.0 nbconvert==6.5.0 # mypy types -types-cachetools==5.0.1 +types-cachetools==5.0.2 types-filelock==3.2.7 types-requests==2.27.30 types-tabulate==0.8.9 From 55fb7656dfdafebf754d6a5b14c8bdd0eca2eb29 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 20 Jun 2022 06:58:41 +0200 Subject: [PATCH 013/220] Update pre-commit cachetools --- .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 f5c1a36f5..e057627cf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: - id: mypy exclude: build_helpers additional_dependencies: - - types-cachetools==5.0.1 + - types-cachetools==5.0.2 - types-filelock==3.2.7 - types-requests==2.27.30 - types-tabulate==0.8.9 From 0804fc7a3af91c25b291bd991132cf77d8d42946 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 20 Jun 2022 07:01:35 +0200 Subject: [PATCH 014/220] CI should run ccxt tests only once --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 551268af7..2f67ec5fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - name: Tests incl. ccxt compatibility tests run: | pytest --random-order --cov=freqtrade --cov-config=.coveragerc --longrun - if: matrix.python-version == '3.9' + if: matrix.python-version == '3.9' and matrix.os == 'ubuntu-22.04' - name: Coveralls if: (runner.os == 'Linux' && matrix.python-version == '3.9') From f9668ede4a54edda390197b3261504b3d526c77d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 20 Jun 2022 07:02:12 +0200 Subject: [PATCH 015/220] Fix CI Syntax error --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f67ec5fe..81a18c4c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - name: Tests incl. ccxt compatibility tests run: | pytest --random-order --cov=freqtrade --cov-config=.coveragerc --longrun - if: matrix.python-version == '3.9' and matrix.os == 'ubuntu-22.04' + if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-22.04' - name: Coveralls if: (runner.os == 'Linux' && matrix.python-version == '3.9') From 50c19ece53644808adf80a95eebefdf6fe3f4c6d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 20 Jun 2022 07:05:51 +0200 Subject: [PATCH 016/220] Fix ccxt test gateio flukyness --- tests/exchange/test_ccxt_compat.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index e016873cb..50154bcaf 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -199,8 +199,13 @@ class TestCCXTExchange(): l2 = exchange.fetch_l2_order_book(pair) assert 'asks' in l2 assert 'bids' in l2 + assert len(l2['asks']) >= 1 + assert len(l2['bids']) >= 1 l2_limit_range = exchange._ft_has['l2_limit_range'] l2_limit_range_required = exchange._ft_has['l2_limit_range_required'] + if exchangename == 'gateio': + # TODO: Gateio is unstable here at the moment, ignoring the limit partially. + return for val in [1, 2, 5, 25, 100]: l2 = exchange.fetch_l2_order_book(pair, val) if not l2_limit_range or val in l2_limit_range: From 996372b8f6c18b9721034bd6abfd41532f3e2b62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jun 2022 05:06:39 +0000 Subject: [PATCH 017/220] Bump colorama from 0.4.4 to 0.4.5 Bumps [colorama](https://github.com/tartley/colorama) from 0.4.4 to 0.4.5. - [Release notes](https://github.com/tartley/colorama/releases) - [Changelog](https://github.com/tartley/colorama/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tartley/colorama/compare/0.4.4...0.4.5) --- updated-dependencies: - dependency-name: colorama 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 b2dbd921e..bd28e3768 100644 --- a/requirements.txt +++ b/requirements.txt @@ -41,7 +41,7 @@ aiofiles==0.8.0 psutil==5.9.1 # Support for colorized terminal output -colorama==0.4.4 +colorama==0.4.5 # Building config files interactively questionary==1.10.0 prompt-toolkit==3.0.29 From e1e3a903f98aebd0d2db6b9c6e0e5f51b70075c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jun 2022 05:07:35 +0000 Subject: [PATCH 018/220] Bump ccxt from 1.87.12 to 1.88.15 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.87.12 to 1.88.15. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.87.12...1.88.15) --- updated-dependencies: - dependency-name: ccxt 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 b2dbd921e..ec244806d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.22.4 pandas==1.4.2 pandas-ta==0.3.14b -ccxt==1.87.12 +ccxt==1.88.15 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.2 aiohttp==3.8.1 From 1cd2b0504a9e1c684326ab59a6dcb6f2a8eb85a7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 20 Jun 2022 07:15:15 +0200 Subject: [PATCH 019/220] Run regular tests for 3.9 under other ubuntu systems --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81a18c4c9..818d250ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: - name: Tests run: | pytest --random-order --cov=freqtrade --cov-config=.coveragerc - if: matrix.python-version != '3.9' + if: matrix.python-version != '3.9' && matrix.os != 'ubuntu-22.04' - name: Tests incl. ccxt compatibility tests run: | From 3189b284c014c4624ba27fc8abbde982c5b36c0c Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 20 Jun 2022 08:04:34 +0200 Subject: [PATCH 020/220] Fix tests condition --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 818d250ca..4fe1ad853 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: - name: Tests run: | pytest --random-order --cov=freqtrade --cov-config=.coveragerc - if: matrix.python-version != '3.9' && matrix.os != 'ubuntu-22.04' + if: matrix.python-version != '3.9' || matrix.os != 'ubuntu-22.04' - name: Tests incl. ccxt compatibility tests run: | From 15fac746a8129e00acb86246e16b00fb7daea89f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jun 2022 06:59:58 +0000 Subject: [PATCH 021/220] Bump mkdocs-material from 8.3.4 to 8.3.6 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.4 to 8.3.6. - [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/8.3.4...8.3.6) --- 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 1f342ca02..6477ad23f 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,5 @@ mkdocs==1.3.0 -mkdocs-material==8.3.4 +mkdocs-material==8.3.6 mdx_truly_sane_lists==1.2 pymdown-extensions==9.5 jinja2==3.1.2 From 405ea74f168ede4d85a4a3d9bf8f6e862ada6b75 Mon Sep 17 00:00:00 2001 From: Surfer Admin Date: Tue, 21 Jun 2022 14:06:41 -0400 Subject: [PATCH 022/220] stopPrice --- .gitignore | 5 ++ freqtrade/templates/sample_strategy.py | 27 ++------ .../templates/strategy_analysis_example.ipynb | 61 ++++++++++++++++--- 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 97f77f779..5042dfb9b 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,8 @@ target/ !config_examples/config_ftx.example.json !config_examples/config_full.example.json !config_examples/config_kraken.example.json +doc/doc-filelist.js +.gitignore +.gitignore +doc/doc-style.css +doc/doc-script.js diff --git a/freqtrade/templates/sample_strategy.py b/freqtrade/templates/sample_strategy.py index 1b375714a..1b49f82c9 100644 --- a/freqtrade/templates/sample_strategy.py +++ b/freqtrade/templates/sample_strategy.py @@ -178,29 +178,10 @@ class SampleStrategy(IStrategy): # RSI dataframe['rsi'] = ta.RSI(dataframe) - # # Inverse Fisher transform on RSI: values [-1.0, 1.0] (https://goo.gl/2JGGoy) - # rsi = 0.1 * (dataframe['rsi'] - 50) - # dataframe['fisher_rsi'] = (np.exp(2 * rsi) - 1) / (np.exp(2 * rsi) + 1) - - # # Inverse Fisher transform on RSI normalized: values [0.0, 100.0] (https://goo.gl/2JGGoy) - # dataframe['fisher_rsi_norma'] = 50 * (dataframe['fisher_rsi'] + 1) - - # # Stochastic Slow - # stoch = ta.STOCH(dataframe) - # dataframe['slowd'] = stoch['slowd'] - # dataframe['slowk'] = stoch['slowk'] - - # Stochastic Fast - stoch_fast = ta.STOCHF(dataframe) - dataframe['fastd'] = stoch_fast['fastd'] - dataframe['fastk'] = stoch_fast['fastk'] - - # # Stochastic RSI - # Please read https://github.com/freqtrade/freqtrade/issues/2961 before using this. - # STOCHRSI is NOT aligned with tradingview, which may result in non-expected results. - # stoch_rsi = ta.STOCHRSI(dataframe) - # dataframe['fastd_rsi'] = stoch_rsi['fastd'] - # dataframe['fastk_rsi'] = stoch_rsi['fastk'] + # Stochastic RSI + stoch_rsi = ta.STOCHRSI(dataframe) + dataframe['fastd_rsi'] = stoch_rsi['fastd'] + dataframe['fastk_rsi'] = stoch_rsi['fastk'] # MACD macd = ta.MACD(dataframe) diff --git a/freqtrade/templates/strategy_analysis_example.ipynb b/freqtrade/templates/strategy_analysis_example.ipynb index 93e4b83ae..33182dbf0 100644 --- a/freqtrade/templates/strategy_analysis_example.ipynb +++ b/freqtrade/templates/strategy_analysis_example.ipynb @@ -19,9 +19,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "OperationalException", + "evalue": "Directory `/Users/surfer/Software/MMM/develop/freqtrade/freqtrade/templates/user_data` does not exist. Please use `freqtrade create-userdir` to create a user directory", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mOperationalException\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [2]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfreqtrade\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mconfiguration\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Configuration\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# Customize these according to your needs.\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m# Initialize empty configuration object\u001b[39;00m\n\u001b[0;32m----> 7\u001b[0m config \u001b[38;5;241m=\u001b[39m \u001b[43mConfiguration\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_files\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;66;03m# Optionally, use existing configuration file\u001b[39;00m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;66;03m# config = Configuration.from_files([\"config.json\"])\u001b[39;00m\n\u001b[1;32m 10\u001b[0m \n\u001b[1;32m 11\u001b[0m \u001b[38;5;66;03m# Define some constants\u001b[39;00m\n\u001b[1;32m 12\u001b[0m config[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtimeframe\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1m\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", + "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:60\u001b[0m, in \u001b[0;36mConfiguration.from_files\u001b[0;34m(files)\u001b[0m\n\u001b[1;32m 58\u001b[0m \u001b[38;5;66;03m# Keep this method as staticmethod, so it can be used from interactive environments\u001b[39;00m\n\u001b[1;32m 59\u001b[0m c \u001b[38;5;241m=\u001b[39m Configuration({\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mconfig\u001b[39m\u001b[38;5;124m'\u001b[39m: files}, RunMode\u001b[38;5;241m.\u001b[39mOTHER)\n\u001b[0;32m---> 60\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:42\u001b[0m, in \u001b[0;36mConfiguration.get_config\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;124;03mReturn the config. Use this method to get the bot config\u001b[39;00m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;124;03m:return: Dict: Bot config\u001b[39;00m\n\u001b[1;32m 40\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconfig \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m---> 42\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconfig \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 44\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconfig\n", + "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:92\u001b[0m, in \u001b[0;36mConfiguration.load_config\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 88\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_common_options(config)\n\u001b[1;32m 90\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_trading_options(config)\n\u001b[0;32m---> 92\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_process_optimize_options\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 94\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_plot_options(config)\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_data_options(config)\n", + "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:249\u001b[0m, in \u001b[0;36mConfiguration._process_optimize_options\u001b[0;34m(self, config)\u001b[0m\n\u001b[1;32m 242\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_args_to_config(config, argname\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mfee\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 243\u001b[0m logstring\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mParameter --fee detected, \u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 244\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124msetting fee to: \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m ...\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 246\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_args_to_config(config, argname\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtimerange\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 247\u001b[0m logstring\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mParameter --timerange detected: \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m ...\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m--> 249\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_process_datadir_options\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 251\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_args_to_config(config, argname\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mstrategy_list\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 252\u001b[0m logstring\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mUsing strategy list of \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m strategies\u001b[39m\u001b[38;5;124m'\u001b[39m, logfun\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mlen\u001b[39m)\n\u001b[1;32m 254\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_args_to_config(\n\u001b[1;32m 255\u001b[0m config,\n\u001b[1;32m 256\u001b[0m argname\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mrecursive_strategy_search\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 257\u001b[0m logstring\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mRecursively searching for a strategy in the strategies folder.\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 258\u001b[0m )\n", + "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:180\u001b[0m, in \u001b[0;36mConfiguration._process_datadir_options\u001b[0;34m(self, config)\u001b[0m\n\u001b[1;32m 177\u001b[0m config\u001b[38;5;241m.\u001b[39mupdate({\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser_data_dir\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;28mstr\u001b[39m(Path\u001b[38;5;241m.\u001b[39mcwd() \u001b[38;5;241m/\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser_data\u001b[39m\u001b[38;5;124m'\u001b[39m)})\n\u001b[1;32m 179\u001b[0m \u001b[38;5;66;03m# reset to user_data_dir so this contains the absolute path.\u001b[39;00m\n\u001b[0;32m--> 180\u001b[0m config[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser_data_dir\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[43mcreate_userdata_dir\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43muser_data_dir\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcreate_dir\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m 181\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mUsing user-data directory: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m ...\u001b[39m\u001b[38;5;124m'\u001b[39m, config[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser_data_dir\u001b[39m\u001b[38;5;124m'\u001b[39m])\n\u001b[1;32m 183\u001b[0m config\u001b[38;5;241m.\u001b[39mupdate({\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdatadir\u001b[39m\u001b[38;5;124m'\u001b[39m: create_datadir(config, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39margs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdatadir\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m))})\n", + "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/directory_operations.py:61\u001b[0m, in \u001b[0;36mcreate_userdata_dir\u001b[0;34m(directory, create_dir)\u001b[0m\n\u001b[1;32m 59\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mCreated user-data directory: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfolder\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OperationalException(\n\u001b[1;32m 62\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mDirectory `\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfolder\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m` does not exist. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 63\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPlease use `freqtrade create-userdir` to create a user directory\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 65\u001b[0m \u001b[38;5;66;03m# Create required subdirectories\u001b[39;00m\n\u001b[1;32m 66\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m f \u001b[38;5;129;01min\u001b[39;00m sub_dirs:\n", + "\u001b[0;31mOperationalException\u001b[0m: Directory `/Users/surfer/Software/MMM/develop/freqtrade/freqtrade/templates/user_data` does not exist. Please use `freqtrade create-userdir` to create a user directory" + ] + } + ], "source": [ "from pathlib import Path\n", "from freqtrade.configuration import Configuration\n", @@ -34,9 +52,9 @@ "# config = Configuration.from_files([\"config.json\"])\n", "\n", "# Define some constants\n", - "config[\"timeframe\"] = \"5m\"\n", + "config[\"timeframe\"] = \"1m\"\n", "# Name of the strategy class\n", - "config[\"strategy\"] = \"SampleStrategy\"\n", + "config[\"strategy\"] = \"MMMOracle\"\n", "# Location of the data\n", "data_location = Path(config['user_data_dir'], 'data', 'binance')\n", "# Pair to analyze - Only use one pair here\n", @@ -136,9 +154,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'config' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [3]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfreqtrade\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdata\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mbtanalysis\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m load_backtest_data, load_backtest_stats\n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# if backtest_dir points to a directory, it'll automatically load the last backtest file.\u001b[39;00m\n\u001b[0;32m----> 4\u001b[0m backtest_dir \u001b[38;5;241m=\u001b[39m \u001b[43mconfig\u001b[49m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124muser_data_dir\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m/\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbacktest_results\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", + "\u001b[0;31mNameError\u001b[0m: name 'config' is not defined" + ] + } + ], "source": [ "from freqtrade.data.btanalysis import load_backtest_data, load_backtest_stats\n", "\n", @@ -247,9 +277,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "Series([], Name: exit_reason, dtype: int64)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from freqtrade.data.btanalysis import load_trades_from_db\n", "\n", @@ -363,7 +404,7 @@ "metadata": { "file_extension": ".py", "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -377,7 +418,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.9.7" }, "mimetype": "text/x-python", "name": "python", From 53e5483daadfac741e21987be8f78b949ad6e808 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 22 Jun 2022 06:30:30 +0200 Subject: [PATCH 023/220] Store StopPrice for dry-run orders closes #6996 --- freqtrade/exchange/binance.py | 13 +++++++++---- freqtrade/exchange/gateio.py | 6 ++++-- freqtrade/exchange/huobi.py | 8 +++++++- freqtrade/exchange/kucoin.py | 5 ++++- freqtrade/persistence/migrations.py | 11 ++++++----- freqtrade/persistence/trade_model.py | 3 +++ tests/exchange/test_kucoin.py | 4 ++-- tests/test_persistence.py | 2 ++ 8 files changed, 37 insertions(+), 15 deletions(-) diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index 03546dcf9..37a3c419d 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -52,10 +52,15 @@ class Binance(Exchange): ordertype = 'stop' if self.trading_mode == TradingMode.FUTURES else 'stop_loss_limit' - return order['type'] == ordertype and ( - (side == "sell" and stop_loss > float(order['stopPrice'])) or - (side == "buy" and stop_loss < float(order['stopPrice'])) - ) + return ( + order.get('stopPrice', None) is None + or ( + order['type'] == ordertype + and ( + (side == "sell" and stop_loss > float(order['stopPrice'])) or + (side == "buy" and stop_loss < float(order['stopPrice'])) + ) + )) def get_tickers(self, symbols: Optional[List[str]] = None, cached: bool = False) -> Dict: tickers = super().get_tickers(symbols=symbols, cached=cached) diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index fd9a2b2b3..bf50167da 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -114,5 +114,7 @@ class Gateio(Exchange): Verify stop_loss against stoploss-order value (limit or price) Returns True if adjustment is necessary. """ - return ((side == "sell" and stop_loss > float(order['stopPrice'])) or - (side == "buy" and stop_loss < float(order['stopPrice']))) + return (order.get('stopPrice', None) is None or ( + side == "sell" and stop_loss > float(order['stopPrice'])) or + (side == "buy" and stop_loss < float(order['stopPrice'])) + ) diff --git a/freqtrade/exchange/huobi.py b/freqtrade/exchange/huobi.py index 71c4d1cf6..736515dec 100644 --- a/freqtrade/exchange/huobi.py +++ b/freqtrade/exchange/huobi.py @@ -27,7 +27,13 @@ class Huobi(Exchange): Verify stop_loss against stoploss-order value (limit or price) Returns True if adjustment is necessary. """ - return order['type'] == 'stop' and stop_loss > float(order['stopPrice']) + return ( + order.get('stopPrice', None) is None + or ( + order['type'] == 'stop' + and stop_loss > float(order['stopPrice']) + ) + ) def _get_stop_params(self, ordertype: str, stop_price: float) -> Dict: diff --git a/freqtrade/exchange/kucoin.py b/freqtrade/exchange/kucoin.py index f23189b3c..21eaa4bc3 100644 --- a/freqtrade/exchange/kucoin.py +++ b/freqtrade/exchange/kucoin.py @@ -33,7 +33,10 @@ class Kucoin(Exchange): Verify stop_loss against stoploss-order value (limit or price) Returns True if adjustment is necessary. """ - return order['info'].get('stop') is not None and stop_loss > float(order['stopPrice']) + return ( + order.get('stopPrice', None) is None + or stop_loss > float(order['stopPrice']) + ) def _get_stop_params(self, ordertype: str, stop_price: float) -> Dict: diff --git a/freqtrade/persistence/migrations.py b/freqtrade/persistence/migrations.py index b0fdf0412..f8fc5d619 100644 --- a/freqtrade/persistence/migrations.py +++ b/freqtrade/persistence/migrations.py @@ -201,16 +201,18 @@ def migrate_orders_table(engine, table_back_name: str, cols_order: List): ft_fee_base = get_column_def(cols_order, 'ft_fee_base', 'null') average = get_column_def(cols_order, 'average', 'null') + stop_price = get_column_def(cols_order, 'stop_price', 'null') # sqlite does not support literals for booleans with engine.begin() as connection: connection.execute(text(f""" insert into orders (id, ft_trade_id, ft_order_side, ft_pair, ft_is_open, order_id, status, symbol, order_type, side, price, amount, filled, average, remaining, cost, - order_date, order_filled_date, order_update_date, ft_fee_base) + stop_price, order_date, order_filled_date, order_update_date, ft_fee_base) select id, ft_trade_id, ft_order_side, ft_pair, ft_is_open, order_id, status, symbol, order_type, side, price, amount, filled, {average} average, remaining, - cost, order_date, order_filled_date, order_update_date, {ft_fee_base} ft_fee_base + cost, {stop_price} stop_price, order_date, order_filled_date, + order_update_date, {ft_fee_base} ft_fee_base from {table_back_name} """)) @@ -294,9 +296,8 @@ def check_migrate(engine, decl_base, previous_tables) -> None: # Check if migration necessary # Migrates both trades and orders table! - # if ('orders' not in previous_tables - # or not has_column(cols_orders, 'leverage')): - if not has_column(cols_trades, 'base_currency'): + if not has_column(cols_orders, 'stop_price'): + # if not has_column(cols_trades, 'base_currency'): logger.info(f"Running database migration for trades - " f"backup: {table_back_name}, {order_table_bak_name}") migrate_trades_and_orders_table( diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 0c8c985c8..324002685 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -57,6 +57,7 @@ class Order(_DECL_BASE): filled = Column(Float, nullable=True) remaining = Column(Float, nullable=True) cost = Column(Float, nullable=True) + stop_price = Column(Float, nullable=True) order_date = Column(DateTime, nullable=True, default=datetime.utcnow) order_filled_date = Column(DateTime, nullable=True) order_update_date = Column(DateTime, nullable=True) @@ -107,6 +108,7 @@ class Order(_DECL_BASE): self.average = order.get('average', self.average) self.remaining = order.get('remaining', self.remaining) self.cost = order.get('cost', self.cost) + self.stop_price = order.get('stopPrice', self.stop_price) if 'timestamp' in order and order['timestamp'] is not None: self.order_date = datetime.fromtimestamp(order['timestamp'] / 1000, tz=timezone.utc) @@ -130,6 +132,7 @@ class Order(_DECL_BASE): 'side': self.ft_order_side, 'filled': self.filled, 'remaining': self.remaining, + 'stopPrice': self.stop_price, 'datetime': self.order_date_utc.strftime('%Y-%m-%dT%H:%M:%S.%f'), 'timestamp': int(self.order_date_utc.timestamp() * 1000), 'status': self.status, diff --git a/tests/exchange/test_kucoin.py b/tests/exchange/test_kucoin.py index 8af1e83a3..ebaf5ae81 100644 --- a/tests/exchange/test_kucoin.py +++ b/tests/exchange/test_kucoin.py @@ -123,5 +123,5 @@ def test_stoploss_adjust_kucoin(mocker, default_conf): assert exchange.stoploss_adjust(1501, order, 'sell') assert not exchange.stoploss_adjust(1499, order, 'sell') # Test with invalid order case - order['info']['stop'] = None - assert not exchange.stoploss_adjust(1501, order, 'sell') + order['stopPrice'] = None + assert exchange.stoploss_adjust(1501, order, 'sell') diff --git a/tests/test_persistence.py b/tests/test_persistence.py index deaad258b..c52e06c82 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -2717,5 +2717,7 @@ def test_order_to_ccxt(limit_buy_order_open): del raw_order['fee'] del raw_order['datetime'] del raw_order['info'] + assert raw_order['stopPrice'] is None + del raw_order['stopPrice'] del limit_buy_order_open['datetime'] assert raw_order == limit_buy_order_open From 90feccf33c4d554c0ea8cbfe31a8b9419b8b24f3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 23 Jun 2022 07:17:24 +0200 Subject: [PATCH 024/220] slightly update custom dockerfile with add. comment closes #6994 --- docker/Dockerfile.custom | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/Dockerfile.custom b/docker/Dockerfile.custom index 3b55fcb0e..6e321f14d 100644 --- a/docker/Dockerfile.custom +++ b/docker/Dockerfile.custom @@ -7,4 +7,5 @@ FROM freqtradeorg/freqtrade:develop # The below dependency - pyti - serves as an example. Please use whatever you need! RUN pip install --user pyti +# Switch back to user (only if you required root above) # USER ftuser From ddc355feb6758f019bb0cdbfb9dfe76bdadd34da Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 23 Jun 2022 08:07:22 +0000 Subject: [PATCH 025/220] Bump numpy from 1.22.4 to 1.23.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 40b5d660d..b62238024 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -numpy==1.22.4 +numpy==1.23.0 pandas==1.4.2 pandas-ta==0.3.14b From 2b07d346118b98bd976200233c57687e9ca28199 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 23 Jun 2022 20:47:51 +0200 Subject: [PATCH 026/220] Revert several undesired changes --- freqtrade/exchange/exchange.py | 8 ++++---- freqtrade/freqtradebot.py | 6 +++--- freqtrade/optimize/backtesting.py | 2 +- freqtrade/plugins/pairlist/PriceFilter.py | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 4fa8f1def..4febe5652 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -383,8 +383,8 @@ class Exchange: Ensures that Configured mode aligns to """ return ( - market.get('quote') is not None - and market.get('base') is not None + market.get('quote', None) is not None + and market.get('base', None) is not None and (self.precisionMode != TICK_SIZE # Too low precision will falsify calculations or market.get('precision', {}).get('price') > 1e-11) @@ -1599,7 +1599,7 @@ class Exchange: def get_fee(self, symbol: str, type: str = '', side: str = '', amount: float = 1, price: float = 1, taker_or_maker: str = 'maker') -> float: try: - if self._config['dry_run'] and self._config.get('fee') is not None: + if self._config['dry_run'] and self._config.get('fee', None) is not None: return self._config['fee'] # validate that markets are loaded before trying to get fee if self._api.markets is None or len(self._api.markets) == 0: @@ -1660,7 +1660,7 @@ class Exchange: fee_to_quote_rate = safe_value_fallback2(tick, tick, 'last', 'ask') except ExchangeError: - fee_to_quote_rate = self._config['exchange'].get('unknown_fee_rate') + fee_to_quote_rate = self._config['exchange'].get('unknown_fee_rate', None) if not fee_to_quote_rate: return None return round((self._contracts_to_amount( diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index affc6f360..ee535e9c3 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -855,7 +855,7 @@ class FreqtradeBot(LoggingMixin): 'order_type': order_type, 'stake_amount': trade.stake_amount, 'stake_currency': self.config['stake_currency'], - 'fiat_currency': self.config.get('fiat_display_currency'), + 'fiat_currency': self.config.get('fiat_display_currency', None), 'amount': safe_value_fallback(order, 'filled', 'amount') or trade.amount, 'open_date': trade.open_date or datetime.utcnow(), 'current_rate': current_rate, @@ -884,7 +884,7 @@ class FreqtradeBot(LoggingMixin): 'order_type': order_type, 'stake_amount': trade.stake_amount, 'stake_currency': self.config['stake_currency'], - 'fiat_currency': self.config.get('fiat_display_currency'), + 'fiat_currency': self.config.get('fiat_display_currency', None), 'amount': trade.amount, 'open_date': trade.open_date, 'current_rate': current_rate, @@ -1590,7 +1590,7 @@ class FreqtradeBot(LoggingMixin): 'open_date': trade.open_date, 'close_date': trade.close_date or datetime.now(timezone.utc), 'stake_currency': self.config['stake_currency'], - 'fiat_currency': self.config.get('fiat_display_currency'), + 'fiat_currency': self.config.get('fiat_display_currency', None), 'reason': reason, } diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 6f566a346..cacb87745 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -123,7 +123,7 @@ class Backtesting: if len(self.pairlists.whitelist) == 0: raise OperationalException("No pair in whitelist.") - if config.get('fee') is not None: + if config.get('fee', None) is not None: self.fee = config['fee'] else: self.fee = self.exchange.get_fee(symbol=self.pairlists.whitelist[0]) diff --git a/freqtrade/plugins/pairlist/PriceFilter.py b/freqtrade/plugins/pairlist/PriceFilter.py index 4c5db52b1..009789eaf 100644 --- a/freqtrade/plugins/pairlist/PriceFilter.py +++ b/freqtrade/plugins/pairlist/PriceFilter.py @@ -70,7 +70,7 @@ class PriceFilter(IPairList): :param ticker: ticker dict as returned from ccxt.fetch_tickers() :return: True if the pair can stay, false if it should be removed """ - if ticker.get('last') is None or ticker.get('last') == 0: + if ticker.get('last', None) is None or ticker.get('last') == 0: self.log_once(f"Removed {pair} from whitelist, because " "ticker['last'] is empty (Usually no trade in the last 24h).", logger.info) From b5d0bc997d6c03b5e8dd0a2a10de4ec58062b2a8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 24 Jun 2022 17:25:33 +0200 Subject: [PATCH 027/220] Clarify stoploss behavior when not defining offset closes #6828 --- docs/stoploss.md | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/docs/stoploss.md b/docs/stoploss.md index 83f787947..6ddb485a4 100644 --- a/docs/stoploss.md +++ b/docs/stoploss.md @@ -130,7 +130,7 @@ In summary: The stoploss will be adjusted to be always be -10% of the highest ob ### Trailing stop loss, custom positive loss -It is also possible to have a default stop loss, when you are in the red with your buy (buy - fee), but once you hit positive result the system will utilize a new stop loss, which can have a different value. +You could also have a default stop loss when you are in the red with your buy (buy - fee), but once you hit a positive result (or an offset you define) the system will utilize a new stop loss, which can have a different value. For example, your default stop loss is -10%, but once you have more than 0% profit (example 0.1%) a different trailing stoploss will be used. !!! Note @@ -142,6 +142,8 @@ Both values require `trailing_stop` to be set to true and `trailing_stop_positiv stoploss = -0.10 trailing_stop = True trailing_stop_positive = 0.02 + trailing_stop_positive_offset = 0.0 + trailing_only_offset_is_reached = False # Default - not necessary for this example ``` For example, simplified math: @@ -156,11 +158,31 @@ For example, simplified math: The 0.02 would translate to a -2% stop loss. Before this, `stoploss` is used for the trailing stoploss. +!!! Tip "Use an offset to change your stoploss" + Use `trailing_stop_positive_offset` to ensure that your new trailing stoploss will be in profit by setting `trailing_stop_positive_offset` higher than `trailing_stop_positive`. Your first new stoploss value will then already have locked in profits. + + Example with simplified math: + + ``` python + stoploss = -0.10 + trailing_stop = True + trailing_stop_positive = 0.02 + trailing_stop_positive_offset = 0.03 + ``` + + * the bot buys an asset at a price of 100$ + * the stop loss is defined at -10%, so the stop loss would get triggered once the asset drops below 90$ + * assuming the asset now increases to 102$ + * the stoploss will now be at 91.8$ - 10% below the highest observed rate + * assuming the asset now increases to 103.5$ (above the offset configured) + * the stop loss will now be -2% of 103$ = 101.42$ + * now the asset drops in value to 102\$, the stop loss will still be 101.42$ and would trigger once price breaks below 101.42$ + ### Trailing stop loss only once the trade has reached a certain offset -It is also possible to use a static stoploss until the offset is reached, and then trail the trade to take profits once the market turns. +You can also keep a static stoploss until the offset is reached, and then trail the trade to take profits once the market turns. -If `"trailing_only_offset_is_reached": true` then the trailing stoploss is only activated once the offset is reached. Until then, the stoploss remains at the configured `stoploss`. +If `trailing_only_offset_is_reached = True` then the trailing stoploss is only activated once the offset is reached. Until then, the stoploss remains at the configured `stoploss`. This option can be used with or without `trailing_stop_positive`, but uses `trailing_stop_positive_offset` as offset. ``` python @@ -203,7 +225,6 @@ If price moves 1% - you've lost 10$ of your own capital - therfore stoploss will Make sure to be aware of this, and avoid using too tight stoploss (at 10x leverage, 10% risk may be too little to allow the trade to "breath" a little). - ## Changing stoploss on open trades A stoploss on an open trade can be changed by changing the value in the configuration or strategy and use the `/reload_config` command (alternatively, completely stopping and restarting the bot also works). From 92dbb0d3660efd602e9851f7b9c35126fc5b5620 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 03:02:07 +0000 Subject: [PATCH 028/220] Bump uvicorn from 0.17.6 to 0.18.1 Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.17.6 to 0.18.1. - [Release notes](https://github.com/encode/uvicorn/releases) - [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md) - [Commits](https://github.com/encode/uvicorn/compare/0.17.6...0.18.1) --- updated-dependencies: - dependency-name: uvicorn 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 b62238024..7781b43e8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -35,7 +35,7 @@ sdnotify==0.3.2 # API Server fastapi==0.78.0 -uvicorn==0.17.6 +uvicorn==0.18.1 pyjwt==2.4.0 aiofiles==0.8.0 psutil==5.9.1 From 4840c7d2fd9f98757fe76ebe90f75f14afb5b814 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 03:02:16 +0000 Subject: [PATCH 029/220] Bump pytest-mock from 3.7.0 to 3.8.1 Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.7.0 to 3.8.1. - [Release notes](https://github.com/pytest-dev/pytest-mock/releases) - [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.7.0...v3.8.1) --- updated-dependencies: - dependency-name: pytest-mock 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 53c85f176..29e21e116 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -12,7 +12,7 @@ pre-commit==2.19.0 pytest==7.1.2 pytest-asyncio==0.18.3 pytest-cov==3.0.0 -pytest-mock==3.7.0 +pytest-mock==3.8.1 pytest-random-order==1.0.4 isort==5.10.1 # For datetime mocking From 45db2347dcd4545fa882cd32fffc9f5d9b936640 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 03:02:29 +0000 Subject: [PATCH 030/220] Bump mkdocs-material from 8.3.6 to 8.3.8 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.6 to 8.3.8. - [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/8.3.6...8.3.8) --- 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 6477ad23f..fe00705b9 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,5 @@ mkdocs==1.3.0 -mkdocs-material==8.3.6 +mkdocs-material==8.3.8 mdx_truly_sane_lists==1.2 pymdown-extensions==9.5 jinja2==3.1.2 From 963f38a69077524a7ce60e2099ae2c641f57c4a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 03:02:46 +0000 Subject: [PATCH 031/220] Bump sqlalchemy from 1.4.37 to 1.4.39 Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.37 to 1.4.39. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy 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 b62238024..7e1bc79e9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ ccxt==1.88.15 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.2 aiohttp==3.8.1 -SQLAlchemy==1.4.37 +SQLAlchemy==1.4.39 python-telegram-bot==13.12 arrow==1.2.2 cachetools==4.2.2 From 8b7dc031f7db50a35731d4b8d92d9196153ae639 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 03:02:51 +0000 Subject: [PATCH 032/220] Bump plotly from 5.8.2 to 5.9.0 Bumps [plotly](https://github.com/plotly/plotly.py) from 5.8.2 to 5.9.0. - [Release notes](https://github.com/plotly/plotly.py/releases) - [Changelog](https://github.com/plotly/plotly.py/blob/master/CHANGELOG.md) - [Commits](https://github.com/plotly/plotly.py/compare/v5.8.2...v5.9.0) --- updated-dependencies: - dependency-name: plotly dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-plot.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-plot.txt b/requirements-plot.txt index a2a894c57..0f6ae94c2 100644 --- a/requirements-plot.txt +++ b/requirements-plot.txt @@ -1,4 +1,4 @@ # Include all requirements to run the bot. -r requirements.txt -plotly==5.8.2 +plotly==5.9.0 From efee148e43e21d0bc90af95ab8e7635bd5624502 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 03:02:53 +0000 Subject: [PATCH 033/220] Bump types-cachetools from 5.0.2 to 5.2.1 Bumps [types-cachetools](https://github.com/python/typeshed) from 5.0.2 to 5.2.1. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-cachetools 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 53c85f176..c3edec904 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -22,7 +22,7 @@ time-machine==2.7.0 nbconvert==6.5.0 # mypy types -types-cachetools==5.0.2 +types-cachetools==5.2.1 types-filelock==3.2.7 types-requests==2.27.30 types-tabulate==0.8.9 From 6510c8d330efedd5f7dad2d48bf566db211f4ce3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 03:03:00 +0000 Subject: [PATCH 034/220] Bump tabulate from 0.8.9 to 0.8.10 Bumps [tabulate](https://github.com/astanin/python-tabulate) from 0.8.9 to 0.8.10. - [Release notes](https://github.com/astanin/python-tabulate/releases) - [Changelog](https://github.com/astanin/python-tabulate/blob/master/CHANGELOG) - [Commits](https://github.com/astanin/python-tabulate/compare/v0.8.9...v0.8.10) --- updated-dependencies: - dependency-name: tabulate 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 b62238024..8f63c5add 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,7 @@ urllib3==1.26.9 jsonschema==4.6.0 TA-Lib==0.4.24 technical==1.3.0 -tabulate==0.8.9 +tabulate==0.8.10 pycoingecko==2.2.0 jinja2==3.1.2 tables==3.7.0 From 0ef2c812db844c9706116ce5b0381e090e62c1e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 05:38:31 +0000 Subject: [PATCH 035/220] Bump ccxt from 1.88.15 to 1.89.14 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.88.15 to 1.89.14. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.88.15...1.89.14) --- updated-dependencies: - dependency-name: ccxt 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 7e1bc79e9..daf8ebd6c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.0 pandas==1.4.2 pandas-ta==0.3.14b -ccxt==1.88.15 +ccxt==1.89.14 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.2 aiohttp==3.8.1 From 9a9d1a89742036169332b4fe37bdeec1dd02293c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 05:39:04 +0000 Subject: [PATCH 036/220] Bump orjson from 3.7.2 to 3.7.3 Bumps [orjson](https://github.com/ijl/orjson) from 3.7.2 to 3.7.3. - [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.7.2...3.7.3) --- updated-dependencies: - dependency-name: orjson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 7e1bc79e9..cf47a80ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,7 @@ urllib3==1.26.9 jsonschema==4.6.0 TA-Lib==0.4.24 technical==1.3.0 -tabulate==0.8.9 +tabulate==0.8.10 pycoingecko==2.2.0 jinja2==3.1.2 tables==3.7.0 @@ -28,7 +28,7 @@ py_find_1st==1.1.5 # Load ticker files 30% faster python-rapidjson==1.6 # Properly format api responses -orjson==3.7.2 +orjson==3.7.3 # Notify systemd sdnotify==0.3.2 From 01185ab48391cf702f187a4dee47417de699ae9f Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 07:59:26 +0200 Subject: [PATCH 037/220] update cachetools precommit --- .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 e057627cf..983df6fad 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: - id: mypy exclude: build_helpers additional_dependencies: - - types-cachetools==5.0.2 + - types-cachetools==5.2.1 - types-filelock==3.2.7 - types-requests==2.27.30 - types-tabulate==0.8.9 From 82ef97af7e16c82ae9ba342fd5b4e945bb590649 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 07:44:33 +0000 Subject: [PATCH 038/220] Bump pandas from 1.4.2 to 1.4.3 Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.4.2 to 1.4.3. - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Changelog](https://github.com/pandas-dev/pandas/blob/main/RELEASE.md) - [Commits](https://github.com/pandas-dev/pandas/compare/v1.4.2...v1.4.3) --- 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 e64ddca05..178d852b0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ numpy==1.23.0 -pandas==1.4.2 +pandas==1.4.3 pandas-ta==0.3.14b ccxt==1.89.14 From d60127a6d8b159ae56e3a4d1ff13a9e225cc0b0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 09:59:07 +0000 Subject: [PATCH 039/220] Bump time-machine from 2.7.0 to 2.7.1 Bumps [time-machine](https://github.com/adamchainz/time-machine) from 2.7.0 to 2.7.1. - [Release notes](https://github.com/adamchainz/time-machine/releases) - [Changelog](https://github.com/adamchainz/time-machine/blob/main/HISTORY.rst) - [Commits](https://github.com/adamchainz/time-machine/compare/2.7.0...2.7.1) --- updated-dependencies: - dependency-name: time-machine 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 ebfbafe07..03773faf6 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -16,7 +16,7 @@ pytest-mock==3.8.1 pytest-random-order==1.0.4 isort==5.10.1 # For datetime mocking -time-machine==2.7.0 +time-machine==2.7.1 # Convert jupyter notebooks to markdown documents nbconvert==6.5.0 From f6e058a327a5e9a3db6e388266d79879186e2cb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 09:59:19 +0000 Subject: [PATCH 040/220] Bump types-requests from 2.27.30 to 2.28.0 Bumps [types-requests](https://github.com/python/typeshed) from 2.27.30 to 2.28.0. - [Release notes](https://github.com/python/typeshed/releases) - [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 ebfbafe07..925bf1929 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,6 +24,6 @@ nbconvert==6.5.0 # mypy types types-cachetools==5.2.1 types-filelock==3.2.7 -types-requests==2.27.30 +types-requests==2.28.0 types-tabulate==0.8.9 types-python-dateutil==2.8.17 From 0c69a0886392114ca65981c923fa357bf53ebd07 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 12:09:27 +0200 Subject: [PATCH 041/220] update requests precommit --- .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 983df6fad..958312d6c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: additional_dependencies: - types-cachetools==5.2.1 - types-filelock==3.2.7 - - types-requests==2.27.30 + - types-requests==2.28.0 - types-tabulate==0.8.9 - types-python-dateutil==2.8.17 # stages: [push] From 8b1798522c17b2f651d4d0653247458ff51709da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 13:18:58 +0000 Subject: [PATCH 042/220] Bump types-tabulate from 0.8.9 to 0.8.11 Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.9 to 0.8.11. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-tabulate 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 852890979..16bb8c47b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -25,5 +25,5 @@ nbconvert==6.5.0 types-cachetools==5.2.1 types-filelock==3.2.7 types-requests==2.28.0 -types-tabulate==0.8.9 +types-tabulate==0.8.11 types-python-dateutil==2.8.17 From 74471e41dbceda78e829e2e377a2773617732e47 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 18:23:00 +0200 Subject: [PATCH 043/220] update tabulate precommit 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 958312d6c..71e230a39 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - types-cachetools==5.2.1 - types-filelock==3.2.7 - types-requests==2.28.0 - - types-tabulate==0.8.9 + - types-tabulate==0.8.11 - types-python-dateutil==2.8.17 # stages: [push] From f2bc35e058cd608a8100c67ed32f626a49451ae9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 20:06:56 +0000 Subject: [PATCH 044/220] Bump types-python-dateutil from 2.8.17 to 2.8.18 Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.17 to 2.8.18. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-python-dateutil 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 16bb8c47b..50cb98fa1 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -26,4 +26,4 @@ types-cachetools==5.2.1 types-filelock==3.2.7 types-requests==2.28.0 types-tabulate==0.8.11 -types-python-dateutil==2.8.17 +types-python-dateutil==2.8.18 From 86f407702419cb23e2c0aa127b1646daed71d363 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 28 Jun 2022 07:37:54 +0200 Subject: [PATCH 045/220] update dateutil precommit --- .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 71e230a39..59e7f6894 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - types-filelock==3.2.7 - types-requests==2.28.0 - types-tabulate==0.8.11 - - types-python-dateutil==2.8.17 + - types-python-dateutil==2.8.18 # stages: [push] - repo: https://github.com/pycqa/isort From 906c7b92fe997c0cb8fcbec3f450b1a601479dba Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 3 Jul 2022 11:05:15 +0200 Subject: [PATCH 046/220] Add enhance testcase to show problematic exit_reason behavior --- tests/test_freqtradebot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 4f3d5f667..4963e2b0a 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -3951,9 +3951,9 @@ def test_ignore_roi_if_entry_signal(default_conf_usdt, limit_order, limit_order_ # Test if entry-signal is absent (should sell due to roi = true) if is_short: - patch_get_signal(freqtrade, enter_long=False, exit_short=False) + patch_get_signal(freqtrade, enter_long=False, exit_short=False, exit_tag='something') else: - patch_get_signal(freqtrade, enter_long=False, exit_long=False) + patch_get_signal(freqtrade, enter_long=False, exit_long=False, exit_tag='something') assert freqtrade.handle_trade(trade) is True assert trade.exit_reason == ExitType.ROI.value From f2fdc21374beee7e06f2d3077c5c3f33b5080a3c Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 3 Jul 2022 11:07:05 +0200 Subject: [PATCH 047/220] Only use exit_tag if exit_type i exit_signal closes #7027 --- freqtrade/freqtradebot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index ee535e9c3..db81a81ba 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1125,9 +1125,10 @@ class FreqtradeBot(LoggingMixin): ) for should_exit in exits: if should_exit.exit_flag: + exit_tag1 = exit_tag if should_exit.exit_type == ExitType.EXIT_SIGNAL else None logger.info(f'Exit for {trade.pair} detected. Reason: {should_exit.exit_type}' - f'{f" Tag: {exit_tag}" if exit_tag is not None else ""}') - exited = self.execute_trade_exit(trade, exit_rate, should_exit, exit_tag=exit_tag) + f'{f" Tag: {exit_tag1}" if exit_tag1 is not None else ""}') + exited = self.execute_trade_exit(trade, exit_rate, should_exit, exit_tag=exit_tag1) if exited: return True return False From c5e6520fee43582496efa2c28b9b21ba2d403235 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 3 Jul 2022 13:35:26 +0200 Subject: [PATCH 048/220] Reorder methods in freqtradebot --- freqtrade/freqtradebot.py | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index db81a81ba..b30c9b965 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -959,6 +959,29 @@ class FreqtradeBot(LoggingMixin): logger.debug(f'Found no {exit_signal_type} signal for %s.', trade) return False + def _check_and_execute_exit(self, trade: Trade, exit_rate: float, + enter: bool, exit_: bool, exit_tag: Optional[str]) -> bool: + """ + Check and execute trade exit + """ + exits: List[ExitCheckTuple] = self.strategy.should_exit( + trade, + exit_rate, + datetime.now(timezone.utc), + enter=enter, + exit_=exit_, + force_stoploss=self.edge.stoploss(trade.pair) if self.edge else 0 + ) + for should_exit in exits: + if should_exit.exit_flag: + exit_tag1 = exit_tag if should_exit.exit_type == ExitType.EXIT_SIGNAL else None + logger.info(f'Exit for {trade.pair} detected. Reason: {should_exit.exit_type}' + f'{f" Tag: {exit_tag1}" if exit_tag1 is not None else ""}') + exited = self.execute_trade_exit(trade, exit_rate, should_exit, exit_tag=exit_tag1) + if exited: + return True + return False + def create_stoploss_order(self, trade: Trade, stop_price: float) -> bool: """ Abstracts creating stoploss orders from the logic. @@ -1110,29 +1133,6 @@ class FreqtradeBot(LoggingMixin): logger.warning(f"Could not create trailing stoploss order " f"for pair {trade.pair}.") - def _check_and_execute_exit(self, trade: Trade, exit_rate: float, - enter: bool, exit_: bool, exit_tag: Optional[str]) -> bool: - """ - Check and execute trade exit - """ - exits: List[ExitCheckTuple] = self.strategy.should_exit( - trade, - exit_rate, - datetime.now(timezone.utc), - enter=enter, - exit_=exit_, - force_stoploss=self.edge.stoploss(trade.pair) if self.edge else 0 - ) - for should_exit in exits: - if should_exit.exit_flag: - exit_tag1 = exit_tag if should_exit.exit_type == ExitType.EXIT_SIGNAL else None - logger.info(f'Exit for {trade.pair} detected. Reason: {should_exit.exit_type}' - f'{f" Tag: {exit_tag1}" if exit_tag1 is not None else ""}') - exited = self.execute_trade_exit(trade, exit_rate, should_exit, exit_tag=exit_tag1) - if exited: - return True - return False - def manage_open_orders(self) -> None: """ Management of open orders on exchange. Unfilled orders might be cancelled if timeout From 07aa372e2a10b2afe3d899d4da3e63c004513788 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 3 Jul 2022 14:10:08 +0200 Subject: [PATCH 049/220] Ensure bot_loop_start is called in hyperopt, too closes #7001 --- docs/bot-basics.md | 5 ++++- freqtrade/optimize/backtesting.py | 3 +-- tests/optimize/test_hyperopt.py | 1 + tests/strategy/strats/hyperoptable_strategy.py | 5 +++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/bot-basics.md b/docs/bot-basics.md index 1acbca565..14823722e 100644 --- a/docs/bot-basics.md +++ b/docs/bot-basics.md @@ -20,7 +20,9 @@ All profit calculations of Freqtrade include fees. For Backtesting / Hyperopt / ## Bot execution logic Starting freqtrade in dry-run or live mode (using `freqtrade trade`) will start the bot and start the bot iteration loop. -By default, loop runs every few seconds (`internals.process_throttle_secs`) and does roughly the following in the following sequence: +This will also run the `bot_start()` callback. + +By default, the bot loop runs every few seconds (`internals.process_throttle_secs`) and performs the following actions: * Fetch open trades from persistence. * Calculate current list of tradable pairs. @@ -54,6 +56,7 @@ This loop will be repeated again and again until the bot is stopped. [backtesting](backtesting.md) or [hyperopt](hyperopt.md) do only part of the above logic, since most of the trading operations are fully simulated. * Load historic data for configured pairlist. +* Calls `bot_start()` once. * Calls `bot_loop_start()` once. * Calculate indicators (calls `populate_indicators()` once per pair). * Calculate entry / exit signals (calls `populate_entry_trend()` and `populate_exit_trend()` once per pair). diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index cacb87745..030d7bdf0 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -189,6 +189,7 @@ class Backtesting: self.strategy.order_types['stoploss_on_exchange'] = False self.strategy.ft_bot_start() + strategy_safe_wrapper(self.strategy.bot_loop_start, supress_error=True)() def _load_protections(self, strategy: IStrategy): if self.config.get('enable_protections', False): @@ -1140,8 +1141,6 @@ class Backtesting: backtest_start_time = datetime.now(timezone.utc) self._set_strategy(strat) - strategy_safe_wrapper(self.strategy.bot_loop_start, supress_error=True)() - # Use max_open_trades in backtesting, except --disable-max-market-positions is set if self.config.get('use_max_market_positions', True): # Must come from strategy config, as the strategy may modify this setting. diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 9f3c5845f..1ad8b33cf 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -861,6 +861,7 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None: hyperopt.backtesting.exchange.get_max_leverage = MagicMock(return_value=1.0) assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto) assert isinstance(hyperopt.backtesting.strategy.buy_rsi, IntParameter) + assert hyperopt.backtesting.strategy.bot_loop_started is True assert hyperopt.backtesting.strategy.buy_rsi.in_space is True assert hyperopt.backtesting.strategy.buy_rsi.value == 35 diff --git a/tests/strategy/strats/hyperoptable_strategy.py b/tests/strategy/strats/hyperoptable_strategy.py index 28ecf617a..876b31b14 100644 --- a/tests/strategy/strats/hyperoptable_strategy.py +++ b/tests/strategy/strats/hyperoptable_strategy.py @@ -44,6 +44,11 @@ class HyperoptableStrategy(StrategyTestV2): }) return prot + bot_loop_started = False + + def bot_loop_start(self): + self.bot_loop_started = True + def bot_start(self, **kwargs) -> None: """ Parameters can also be defined here ... From 92d189a84f8c8eaa4d7b727aeb890a46adab7b40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 03:02:30 +0000 Subject: [PATCH 050/220] Bump orjson from 3.7.3 to 3.7.6 Bumps [orjson](https://github.com/ijl/orjson) from 3.7.3 to 3.7.6. - [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.7.3...3.7.6) --- 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 961cfc774..d2213f71a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,7 +28,7 @@ py_find_1st==1.1.5 # Load ticker files 30% faster python-rapidjson==1.6 # Properly format api responses -orjson==3.7.3 +orjson==3.7.6 # Notify systemd sdnotify==0.3.2 From b16bb23cc8c221ba05d15bb4d918fe8b8e3e9714 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 03:02:34 +0000 Subject: [PATCH 051/220] Bump prompt-toolkit from 3.0.29 to 3.0.30 Bumps [prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) from 3.0.29 to 3.0.30. - [Release notes](https://github.com/prompt-toolkit/python-prompt-toolkit/releases) - [Changelog](https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/CHANGELOG) - [Commits](https://github.com/prompt-toolkit/python-prompt-toolkit/compare/3.0.29...3.0.30) --- updated-dependencies: - dependency-name: prompt-toolkit 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 961cfc774..e6d5d171f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,7 +44,7 @@ psutil==5.9.1 colorama==0.4.5 # Building config files interactively questionary==1.10.0 -prompt-toolkit==3.0.29 +prompt-toolkit==3.0.30 # Extensions to datetime library python-dateutil==2.8.2 From 0555d7783c59c41283b21a9d67271b3d4ebc9576 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 03:02:40 +0000 Subject: [PATCH 052/220] Bump python-telegram-bot from 13.12 to 13.13 Bumps [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) from 13.12 to 13.13. - [Release notes](https://github.com/python-telegram-bot/python-telegram-bot/releases) - [Changelog](https://github.com/python-telegram-bot/python-telegram-bot/blob/v13.13/CHANGES.rst) - [Commits](https://github.com/python-telegram-bot/python-telegram-bot/compare/v13.12...v13.13) --- updated-dependencies: - dependency-name: python-telegram-bot 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 961cfc774..b30f4ddfd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ ccxt==1.89.14 cryptography==37.0.2 aiohttp==3.8.1 SQLAlchemy==1.4.39 -python-telegram-bot==13.12 +python-telegram-bot==13.13 arrow==1.2.2 cachetools==4.2.2 requests==2.28.0 From 9a8d03b1f58d7abcbbca8d8510b5da0dc732643d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 03:03:02 +0000 Subject: [PATCH 053/220] Bump uvicorn from 0.18.1 to 0.18.2 Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.18.1 to 0.18.2. - [Release notes](https://github.com/encode/uvicorn/releases) - [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md) - [Commits](https://github.com/encode/uvicorn/compare/0.18.1...0.18.2) --- updated-dependencies: - dependency-name: uvicorn 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 961cfc774..2cfdf527e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -35,7 +35,7 @@ sdnotify==0.3.2 # API Server fastapi==0.78.0 -uvicorn==0.18.1 +uvicorn==0.18.2 pyjwt==2.4.0 aiofiles==0.8.0 psutil==5.9.1 From dd21d963fc48b0fea6b26867d8414f375df22548 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 05:09:28 +0000 Subject: [PATCH 054/220] Bump ccxt from 1.89.14 to 1.89.96 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.89.14 to 1.89.96. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.89.14...1.89.96) --- 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 b30f4ddfd..bbbd61bfc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.0 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.89.14 +ccxt==1.89.96 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.2 aiohttp==3.8.1 From 0a8a0c66b4877a40efa6c8a92c8d00ca9d369c9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 05:10:00 +0000 Subject: [PATCH 055/220] Bump requests from 2.28.0 to 2.28.1 Bumps [requests](https://github.com/psf/requests) from 2.28.0 to 2.28.1. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.28.0...v2.28.1) --- updated-dependencies: - dependency-name: requests 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 2e0dfe6d6..5a5cc1307 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ SQLAlchemy==1.4.39 python-telegram-bot==13.13 arrow==1.2.2 cachetools==4.2.2 -requests==2.28.0 +requests==2.28.1 urllib3==1.26.9 jsonschema==4.6.0 TA-Lib==0.4.24 From 5820fc3b44e5886486cf238cff2a3ca28bbca9c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 05:55:44 +0000 Subject: [PATCH 056/220] Bump jsonschema from 4.6.0 to 4.6.1 Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.6.0 to 4.6.1. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.6.0...v4.6.1) --- updated-dependencies: - dependency-name: jsonschema 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 0aec2c5b8..04c31dddf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ arrow==1.2.2 cachetools==4.2.2 requests==2.28.1 urllib3==1.26.9 -jsonschema==4.6.0 +jsonschema==4.6.1 TA-Lib==0.4.24 technical==1.3.0 tabulate==0.8.10 From 6da3fa08e4644c3e5618c36ed7fde919d0eae239 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 4 Jul 2022 11:14:59 +0200 Subject: [PATCH 057/220] Update migrations to also support Postgres closes #7038 --- freqtrade/persistence/migrations.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/persistence/migrations.py b/freqtrade/persistence/migrations.py index f8fc5d619..8373b3376 100644 --- a/freqtrade/persistence/migrations.py +++ b/freqtrade/persistence/migrations.py @@ -255,8 +255,8 @@ def fix_old_dry_orders(engine): text( """ update orders - set ft_is_open = 0 - where ft_is_open = 1 and (ft_trade_id, order_id) not in ( + set ft_is_open = false + where ft_is_open = true and (ft_trade_id, order_id) not in ( select id, stoploss_order_id from trades where stoploss_order_id is not null ) and ft_order_side = 'stoploss' and order_id like 'dry_%' @@ -267,8 +267,8 @@ def fix_old_dry_orders(engine): text( """ update orders - set ft_is_open = 0 - where ft_is_open = 1 + set ft_is_open = false + where ft_is_open = true and (ft_trade_id, order_id) not in ( select id, open_order_id from trades where open_order_id is not null ) and ft_order_side != 'stoploss' From fe8083c7f8835d77ff1d7c681f10b780a2cb94b6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 4 Jul 2022 17:17:01 +0200 Subject: [PATCH 058/220] Improve test for dry-run orderclosing --- tests/test_persistence.py | 59 +++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/tests/test_persistence.py b/tests/test_persistence.py index c52e06c82..a09711048 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -1200,7 +1200,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog): 0.00258580, {stake}, {amount}, '2019-11-28 12:44:24.000000', 0.0, 0.0, 0.0, '5m', - 'buy_order', 'stop_order_id222') + 'buy_order', 'dry_stop_order_id222') """.format(fee=fee.return_value, stake=default_conf.get("stake_amount"), amount=amount @@ -1226,7 +1226,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog): 'buy', 'ETC/BTC', 0, - 'buy_order', + 'dry_buy_order', 'closed', 'ETC/BTC', 'limit', @@ -1238,12 +1238,44 @@ def test_migrate_new(mocker, default_conf, fee, caplog): {amount * 0.00258580} ), ( + 1, + 'buy', + 'ETC/BTC', + 1, + 'dry_buy_order22', + 'canceled', + 'ETC/BTC', + 'limit', + 'buy', + 0.00258580, + {amount}, + {amount}, + 0, + {amount * 0.00258580} + ), + ( 1, 'stoploss', 'ETC/BTC', + 1, + 'dry_stop_order_id11X', + 'canceled', + 'ETC/BTC', + 'limit', + 'sell', + 0.00258580, + {amount}, + {amount}, 0, - 'stop_order_id222', - 'closed', + {amount * 0.00258580} + ), + ( + 1, + 'stoploss', + 'ETC/BTC', + 1, + 'dry_stop_order_id222', + 'open', 'ETC/BTC', 'limit', 'sell', @@ -1292,7 +1324,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog): assert trade.exit_reason is None assert trade.strategy is None assert trade.timeframe == '5m' - assert trade.stoploss_order_id == 'stop_order_id222' + assert trade.stoploss_order_id == 'dry_stop_order_id222' assert trade.stoploss_last_update is None assert log_has("trying trades_bak1", caplog) assert log_has("trying trades_bak2", caplog) @@ -1302,12 +1334,21 @@ def test_migrate_new(mocker, default_conf, fee, caplog): assert trade.close_profit_abs is None orders = trade.orders - assert len(orders) == 2 - assert orders[0].order_id == 'buy_order' + assert len(orders) == 4 + assert orders[0].order_id == 'dry_buy_order' assert orders[0].ft_order_side == 'buy' - assert orders[1].order_id == 'stop_order_id222' - assert orders[1].ft_order_side == 'stoploss' + assert orders[-1].order_id == 'dry_stop_order_id222' + assert orders[-1].ft_order_side == 'stoploss' + assert orders[-1].ft_is_open is True + + assert orders[1].order_id == 'dry_buy_order22' + assert orders[1].ft_order_side == 'buy' + assert orders[1].ft_is_open is False + + assert orders[2].order_id == 'dry_stop_order_id11X' + assert orders[2].ft_order_side == 'stoploss' + assert orders[2].ft_is_open is False def test_migrate_too_old(mocker, default_conf, fee, caplog): From 6f0721ae2b1a7fe47f8844887e72472af46f4ad3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 4 Jul 2022 17:17:39 +0200 Subject: [PATCH 059/220] Update dry-order-fix to use sqlalchemy internals --- freqtrade/persistence/migrations.py | 53 +++++++++++++++-------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/freqtrade/persistence/migrations.py b/freqtrade/persistence/migrations.py index 8373b3376..2a8e34cdf 100644 --- a/freqtrade/persistence/migrations.py +++ b/freqtrade/persistence/migrations.py @@ -1,9 +1,10 @@ import logging from typing import List -from sqlalchemy import inspect, text +from sqlalchemy import inspect, select, text, tuple_, update from freqtrade.exceptions import OperationalException +from freqtrade.persistence.trade_model import Order, Trade logger = logging.getLogger(__name__) @@ -251,31 +252,31 @@ def set_sqlite_to_wal(engine): def fix_old_dry_orders(engine): with engine.begin() as connection: - connection.execute( - text( - """ - update orders - set ft_is_open = false - where ft_is_open = true and (ft_trade_id, order_id) not in ( - select id, stoploss_order_id from trades where stoploss_order_id is not null - ) and ft_order_side = 'stoploss' - and order_id like 'dry_%' - """ - ) - ) - connection.execute( - text( - """ - update orders - set ft_is_open = false - where ft_is_open = true - and (ft_trade_id, order_id) not in ( - select id, open_order_id from trades where open_order_id is not null - ) and ft_order_side != 'stoploss' - and order_id like 'dry_%' - """ - ) - ) + stmt = update(Order).where( + Order.ft_is_open.is_(True), + tuple_(Order.ft_trade_id, Order.order_id).not_in( + select( + Trade.id, Trade.stoploss_order_id + ).where(Trade.stoploss_order_id.is_not(None)) + ), + Order.ft_order_side == 'stoploss', + Order.order_id.like('dry%'), + + ).values(ft_is_open=False) + connection.execute(stmt) + + stmt = update(Order).where( + Order.ft_is_open.is_(True), + tuple_(Order.ft_trade_id, Order.order_id).not_in( + select( + Trade.id, Trade.open_order_id + ).where(Trade.open_order_id.is_not(None)) + ), + Order.ft_order_side != 'stoploss', + Order.order_id.like('dry%') + + ).values(ft_is_open=False) + connection.execute(stmt) def check_migrate(engine, decl_base, previous_tables) -> None: From 647f9b5460e9b1cf247e63bd6ff2c857d8f802a8 Mon Sep 17 00:00:00 2001 From: robcaulk Date: Tue, 5 Jul 2022 12:49:09 +0200 Subject: [PATCH 060/220] replace the word abortion with rejected in log messages --- freqtrade/freqtradebot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index b30c9b965..4897a279c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -634,7 +634,7 @@ class FreqtradeBot(LoggingMixin): pair=pair, order_type=order_type, amount=amount, rate=enter_limit_requested, time_in_force=time_in_force, current_time=datetime.now(timezone.utc), entry_tag=enter_tag, side=trade_side): - logger.info(f"User requested abortion of buying {pair}") + logger.info(f"User rejected entry for {pair}.") return False order = self.exchange.create_order( pair=pair, @@ -1465,7 +1465,7 @@ class FreqtradeBot(LoggingMixin): time_in_force=time_in_force, exit_reason=exit_reason, sell_reason=exit_reason, # sellreason -> compatibility current_time=datetime.now(timezone.utc)): - logger.info(f"User requested abortion of {trade.pair} exit.") + logger.info(f"User rejected exit for {trade.pair}.") return False try: From 514f7d491c6ecab3abb4b9ea69457d2d67e3a25a Mon Sep 17 00:00:00 2001 From: robcaulk Date: Tue, 5 Jul 2022 12:58:43 +0200 Subject: [PATCH 061/220] change rejected to denied --- freqtrade/freqtradebot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 4897a279c..f242e001b 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -634,7 +634,7 @@ class FreqtradeBot(LoggingMixin): pair=pair, order_type=order_type, amount=amount, rate=enter_limit_requested, time_in_force=time_in_force, current_time=datetime.now(timezone.utc), entry_tag=enter_tag, side=trade_side): - logger.info(f"User rejected entry for {pair}.") + logger.info(f"User denied entry for {pair}.") return False order = self.exchange.create_order( pair=pair, @@ -1465,7 +1465,7 @@ class FreqtradeBot(LoggingMixin): time_in_force=time_in_force, exit_reason=exit_reason, sell_reason=exit_reason, # sellreason -> compatibility current_time=datetime.now(timezone.utc)): - logger.info(f"User rejected exit for {trade.pair}.") + logger.info(f"User denied exit for {trade.pair}.") return False try: From dbc3376fe900563d86748a6549c862af9a65c444 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 5 Jul 2022 20:46:09 +0200 Subject: [PATCH 062/220] Add alias for gate to gateio --- freqtrade/exchange/common.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/exchange/common.py b/freqtrade/exchange/common.py index 841f45cd0..f2d460bfe 100644 --- a/freqtrade/exchange/common.py +++ b/freqtrade/exchange/common.py @@ -46,6 +46,7 @@ MAP_EXCHANGE_CHILDCLASS = { 'binanceje': 'binance', 'binanceusdm': 'binance', 'okex': 'okx', + 'gate': 'gateio', } SUPPORTED_EXCHANGES = [ From 2dc46ca0b8cfc4c78d4eb387cbb50046e736c8bf Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 6 Jul 2022 07:07:28 +0200 Subject: [PATCH 063/220] Add cost to partial test buy order --- tests/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/conftest.py b/tests/conftest.py index e9161d77e..2e447c281 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1694,6 +1694,7 @@ def limit_buy_order_old_partial(): 'price': 0.00001099, 'amount': 90.99181073, 'filled': 23.0, + 'cost': 90.99181073 * 23.0, 'remaining': 67.99181073, 'status': 'open' } From b39508f64da470e7f05f9af3a50bf1f644a1b737 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 7 Jul 2022 19:44:54 +0200 Subject: [PATCH 064/220] remove loadMarkets from "required" section, it's now implied that all ccxt exchanges provide this method. --- freqtrade/exchange/common.py | 1 - 1 file changed, 1 deletion(-) diff --git a/freqtrade/exchange/common.py b/freqtrade/exchange/common.py index f2d460bfe..e5b6533c4 100644 --- a/freqtrade/exchange/common.py +++ b/freqtrade/exchange/common.py @@ -68,7 +68,6 @@ EXCHANGE_HAS_REQUIRED = [ 'fetchBalance', # Public endpoints - 'loadMarkets', 'fetchOHLCV', ] From e52f82b565fa713951ffc70b84215aab217a1d73 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 8 Jul 2022 19:44:20 +0200 Subject: [PATCH 065/220] Add leverage to custom_stake_amount callback closes #7047 --- docs/strategy-callbacks.md | 10 ++++++---- freqtrade/freqtradebot.py | 2 +- freqtrade/optimize/backtesting.py | 2 +- freqtrade/strategy/interface.py | 4 +++- .../subtemplates/strategy_methods_advanced.j2 | 6 ++++-- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index beffba56b..f584bd1bb 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -82,8 +82,9 @@ Called before entering a trade, makes it possible to manage your position size w ```python class AwesomeStrategy(IStrategy): def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, - proposed_stake: float, min_stake: float, max_stake: float, - entry_tag: Optional[str], side: str, **kwargs) -> float: + proposed_stake: float, min_stake: Optional[float], max_stake: float, + leverage: float, entry_tag: Optional[str], side: str, + **kwargs) -> float: dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) current_candle = dataframe.iloc[-1].squeeze() @@ -673,9 +674,10 @@ class DigDeeperStrategy(IStrategy): max_dca_multiplier = 5.5 # This is called when placing the initial order (opening trade) - def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, +def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, proposed_stake: float, min_stake: Optional[float], max_stake: float, - entry_tag: Optional[str], side: str, **kwargs) -> float: + leverage: float, entry_tag: Optional[str], side: str, + **kwargs) -> float: # We need to leave most of the funds for possible further DCA orders # This also applies to fixed stakes diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index f242e001b..d1404807d 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -814,7 +814,7 @@ class FreqtradeBot(LoggingMixin): pair=pair, current_time=datetime.now(timezone.utc), current_rate=enter_limit_requested, proposed_stake=stake_amount, min_stake=min_stake_amount, max_stake=min(max_stake_amount, stake_available), - entry_tag=entry_tag, side=trade_side + leverage=leverage, entry_tag=entry_tag, side=trade_side ) stake_amount = self.wallets.validate_stake_amount( diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 030d7bdf0..da28a8d93 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -722,7 +722,7 @@ class Backtesting: pair=pair, current_time=current_time, current_rate=propose_rate, proposed_stake=stake_amount, min_stake=min_stake_amount, max_stake=min(stake_available, max_stake_amount), - entry_tag=entry_tag, side=direction) + leverage=leverage, entry_tag=entry_tag, side=direction) stake_amount_val = self.wallets.validate_stake_amount( pair=pair, diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index d4ccfc5db..c60817c99 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -442,7 +442,8 @@ class IStrategy(ABC, HyperStrategyMixin): def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, proposed_stake: float, min_stake: Optional[float], max_stake: float, - entry_tag: Optional[str], side: str, **kwargs) -> float: + leverage: float, entry_tag: Optional[str], side: str, + **kwargs) -> float: """ Customize stake size for each new trade. @@ -452,6 +453,7 @@ class IStrategy(ABC, HyperStrategyMixin): :param proposed_stake: A stake amount proposed by the bot. :param min_stake: Minimal stake size allowed by exchange. :param max_stake: Balance available for trading. + :param leverage: Leverage selected for this trade. :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal. :param side: 'long' or 'short' - indicating the direction of the proposed trade :return: A stake size, which is between min_stake and max_stake. diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index 815ca7cd3..989f1d37a 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -79,9 +79,10 @@ def custom_exit_price(self, pair: str, trade: 'Trade', """ return proposed_rate -def custom_stake_amount(self, pair: str, current_time: 'datetime', current_rate: float, +def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, proposed_stake: float, min_stake: Optional[float], max_stake: float, - entry_tag: 'Optional[str]', side: str, **kwargs) -> float: + leverage: float, entry_tag: Optional[str], side: str, + **kwargs) -> float: """ Customize stake size for each new trade. @@ -91,6 +92,7 @@ def custom_stake_amount(self, pair: str, current_time: 'datetime', current_rate: :param proposed_stake: A stake amount proposed by the bot. :param min_stake: Minimal stake size allowed by exchange. :param max_stake: Balance available for trading. + :param leverage: Leverage selected for this trade. :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal. :param side: 'long' or 'short' - indicating the direction of the proposed trade :return: A stake size, which is between min_stake and max_stake. From 2499276fca84123700d34eb023a938651b57c111 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 6 Jul 2022 19:15:55 +0200 Subject: [PATCH 066/220] Refactor calculate_fee_rate to take separate parameters instead of an "Order" we passed in a trade object anyway --- freqtrade/exchange/exchange.py | 49 +++++++++++++++++++++------------ freqtrade/freqtradebot.py | 7 +++-- tests/exchange/test_exchange.py | 5 ++-- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 4febe5652..ced1c71fb 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1631,27 +1631,30 @@ class Exchange: and order['fee']['cost'] is not None ) - def calculate_fee_rate(self, order: Dict) -> Optional[float]: + def calculate_fee_rate( + self, fee: Dict, symbol: str, cost: float, amount: float) -> Optional[float]: """ Calculate fee rate if it's not given by the exchange. - :param order: Order or trade (one trade) dict + :param fee: ccxt Fee dict - must contain cost / currency / rate + :param symbol: Symbol of the order + :param cost: Total cost of the order + :param amount: Amount of the order """ - if order['fee'].get('rate') is not None: - return order['fee'].get('rate') - fee_curr = order['fee']['currency'] + if fee.get('rate') is not None: + return fee.get('rate') + fee_curr = fee['currency'] # Calculate fee based on order details - if fee_curr in self.get_pair_base_currency(order['symbol']): + if fee_curr in self.get_pair_base_currency(symbol): # Base currency - divide by amount - return round( - order['fee']['cost'] / safe_value_fallback2(order, order, 'filled', 'amount'), 8) - elif fee_curr in self.get_pair_quote_currency(order['symbol']): + return round(fee['cost'] / amount, 8) + elif fee_curr in self.get_pair_quote_currency(symbol): # Quote currency - divide by cost return round(self._contracts_to_amount( - order['symbol'], order['fee']['cost']) / order['cost'], - 8) if order['cost'] else None + symbol, fee['cost']) / cost, + 8) if cost else None else: # If Fee currency is a different currency - if not order['cost']: + if not cost: # If cost is None or 0.0 -> falsy, return None return None try: @@ -1664,18 +1667,28 @@ class Exchange: if not fee_to_quote_rate: return None return round((self._contracts_to_amount( - order['symbol'], order['fee']['cost']) * fee_to_quote_rate) / order['cost'], 8) + symbol, fee['cost']) * fee_to_quote_rate) / cost, 8) - def extract_cost_curr_rate(self, order: Dict) -> Tuple[float, str, Optional[float]]: + def extract_cost_curr_rate(self, fee: Dict, symbol: str, cost: float, + amount: float) -> Tuple[float, str, Optional[float]]: """ Extract tuple of cost, currency, rate. Requires order_has_fee to run first! - :param order: Order or trade (one trade) dict + :param fee: ccxt Fee dict - must contain cost / currency / rate + :param symbol: Symbol of the order + :param cost: Total cost of the order + :param amount: Amount of the order :return: Tuple with cost, currency, rate of the given fee dict """ - return (order['fee']['cost'], - order['fee']['currency'], - self.calculate_fee_rate(order)) + return (fee['cost'], + fee['currency'], + self.calculate_fee_rate( + fee, + symbol, + cost, + amount + ) + ) # Historic data diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index d1404807d..e0532a17d 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1742,7 +1742,8 @@ class FreqtradeBot(LoggingMixin): trade_base_currency = self.exchange.get_pair_base_currency(trade.pair) # use fee from order-dict if possible if self.exchange.order_has_fee(order): - fee_cost, fee_currency, fee_rate = self.exchange.extract_cost_curr_rate(order) + fee_cost, fee_currency, fee_rate = self.exchange.extract_cost_curr_rate( + order['fee'], order['symbol'], order['cost'], order_obj.safe_filled) logger.info(f"Fee for Trade {trade} [{order_obj.ft_order_side}]: " f"{fee_cost:.8g} {fee_currency} - rate: {fee_rate}") if fee_rate is None or fee_rate < 0.02: @@ -1780,7 +1781,9 @@ class FreqtradeBot(LoggingMixin): for exectrade in trades: amount += exectrade['amount'] if self.exchange.order_has_fee(exectrade): - fee_cost_, fee_currency, fee_rate_ = self.exchange.extract_cost_curr_rate(exectrade) + fee_cost_, fee_currency, fee_rate_ = self.exchange.extract_cost_curr_rate( + exectrade['fee'], exectrade['symbol'], exectrade['cost'], exectrade['amount'] + ) fee_cost += fee_cost_ if fee_rate_ is not None: fee_rate_array.append(fee_rate_) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 708a0e889..0dc1b1741 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3544,7 +3544,7 @@ def test_order_has_fee(order, expected) -> None: def test_extract_cost_curr_rate(mocker, default_conf, order, expected) -> None: mocker.patch('freqtrade.exchange.Exchange.calculate_fee_rate', MagicMock(return_value=0.01)) ex = get_patched_exchange(mocker, default_conf) - assert ex.extract_cost_curr_rate(order) == expected + assert ex.extract_cost_curr_rate(order['fee'], order['symbol'], cost=20, amount=1) == expected @pytest.mark.parametrize("order,unknown_fee_rate,expected", [ @@ -3590,7 +3590,8 @@ def test_calculate_fee_rate(mocker, default_conf, order, expected, unknown_fee_r ex = get_patched_exchange(mocker, default_conf) - assert ex.calculate_fee_rate(order) == expected + assert ex.calculate_fee_rate(order['fee'], order['symbol'], + cost=order['cost'], amount=order['amount']) == expected @pytest.mark.parametrize('retrycount,max_retries,expected', [ From 81f7d77d7440e8a64d3ff2bf0b7b8ef7eb0ff7a0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 7 Jul 2022 07:08:49 +0200 Subject: [PATCH 067/220] Allow fee currency to be empty for futures --- freqtrade/exchange/exchange.py | 22 +++++++++++++--------- tests/exchange/test_exchange.py | 6 ++++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index ced1c71fb..cdfd8aa79 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1615,8 +1615,7 @@ class Exchange: except ccxt.BaseError as e: raise OperationalException(e) from e - @staticmethod - def order_has_fee(order: Dict) -> bool: + def order_has_fee(self, order: Dict) -> bool: """ Verifies if the passed in order dict has the needed keys to extract fees, and that these keys (currency, cost) are not empty. @@ -1627,7 +1626,8 @@ class Exchange: return False return ('fee' in order and order['fee'] is not None and (order['fee'].keys() >= {'currency', 'cost'}) - and order['fee']['currency'] is not None + and (order['fee']['currency'] is not None + or self.trading_mode == TradingMode.FUTURES) and order['fee']['cost'] is not None ) @@ -1642,16 +1642,20 @@ class Exchange: """ if fee.get('rate') is not None: return fee.get('rate') - fee_curr = fee['currency'] + fee_curr = fee.get('currency') + if fee_curr is None: + # Auto-currency only in futures mode + if self.trading_mode == TradingMode.FUTURES: + fee_curr = self.get_pair_quote_currency(symbol) + else: + return None # Calculate fee based on order details - if fee_curr in self.get_pair_base_currency(symbol): + if fee_curr == self.get_pair_base_currency(symbol): # Base currency - divide by amount return round(fee['cost'] / amount, 8) - elif fee_curr in self.get_pair_quote_currency(symbol): + elif fee_curr == self.get_pair_quote_currency(symbol): # Quote currency - divide by cost - return round(self._contracts_to_amount( - symbol, fee['cost']) / cost, - 8) if cost else None + return round(self._contracts_to_amount(symbol, fee['cost']) / cost, 8) if cost else None else: # If Fee currency is a different currency if not cost: diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 0dc1b1741..f1d430437 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3529,8 +3529,10 @@ def test_market_is_active(market, expected_result) -> None: ({'fee': {'currency': 'ETH/BTC', 'cost': None}}, False), ({'fee': {'currency': 'ETH/BTC', 'cost': 0.01}}, True), ]) -def test_order_has_fee(order, expected) -> None: - assert Exchange.order_has_fee(order) == expected +def test_order_has_fee(mocker, default_conf, order, expected) -> None: + ex = get_patched_exchange(mocker, default_conf) + + assert ex.order_has_fee(order) == expected @pytest.mark.parametrize("order,expected", [ From 5b733a723df398e67a9e2fb8d233cbfbe0b0389f Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 7 Jul 2022 19:40:16 +0200 Subject: [PATCH 068/220] use "fees" for trades responses --- freqtrade/exchange/exchange.py | 6 +----- freqtrade/freqtradebot.py | 9 ++++++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index cdfd8aa79..c192ca830 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1644,11 +1644,7 @@ class Exchange: return fee.get('rate') fee_curr = fee.get('currency') if fee_curr is None: - # Auto-currency only in futures mode - if self.trading_mode == TradingMode.FUTURES: - fee_curr = self.get_pair_quote_currency(symbol) - else: - return None + return None # Calculate fee based on order details if fee_curr == self.get_pair_base_currency(symbol): # Base currency - divide by amount diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index e0532a17d..3fd134078 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1777,12 +1777,19 @@ class FreqtradeBot(LoggingMixin): fee_abs = 0.0 fee_cost = 0.0 trade_base_currency = self.exchange.get_pair_base_currency(trade.pair) + fee_rate_array: List[float] = [] for exectrade in trades: amount += exectrade['amount'] if self.exchange.order_has_fee(exectrade): + # Prefer singular fee + fees = [exectrade['fee']] + else: + fees = exectrade.get('fees', []) + for fee in fees: + fee_cost_, fee_currency, fee_rate_ = self.exchange.extract_cost_curr_rate( - exectrade['fee'], exectrade['symbol'], exectrade['cost'], exectrade['amount'] + fee, exectrade['symbol'], exectrade['cost'], exectrade['amount'] ) fee_cost += fee_cost_ if fee_rate_ is not None: From b7167ec88088a3541e6958233d98f8c4869053b3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 9 Jul 2022 08:24:29 +0200 Subject: [PATCH 069/220] Fix wrong fee calclulation for gateio futures --- freqtrade/exchange/exchange.py | 11 ++++++++--- freqtrade/exchange/gateio.py | 3 ++- freqtrade/exchange/okx.py | 1 + freqtrade/freqtradebot.py | 1 - freqtrade/persistence/trade_model.py | 2 +- tests/exchange/test_exchange.py | 3 +++ 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index c192ca830..fdf323582 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -77,6 +77,7 @@ class Exchange: "mark_ohlcv_price": "mark", "mark_ohlcv_timeframe": "8h", "ccxt_futures_name": "swap", + "fee_cost_in_contracts": False, # Fee cost needs contract conversion "needs_trading_fees": False, # use fetch_trading_fees to cache fees } _ft_has: Dict = {} @@ -1645,13 +1646,18 @@ class Exchange: fee_curr = fee.get('currency') if fee_curr is None: return None + fee_cost = fee['cost'] + if self._ft_has['fee_cost_in_contracts']: + # Convert cost via "contracts" conversion + fee_cost = self._contracts_to_amount(symbol, fee['cost']) + # Calculate fee based on order details if fee_curr == self.get_pair_base_currency(symbol): # Base currency - divide by amount return round(fee['cost'] / amount, 8) elif fee_curr == self.get_pair_quote_currency(symbol): # Quote currency - divide by cost - return round(self._contracts_to_amount(symbol, fee['cost']) / cost, 8) if cost else None + return round(fee_cost / cost, 8) if cost else None else: # If Fee currency is a different currency if not cost: @@ -1666,8 +1672,7 @@ class Exchange: fee_to_quote_rate = self._config['exchange'].get('unknown_fee_rate', None) if not fee_to_quote_rate: return None - return round((self._contracts_to_amount( - symbol, fee['cost']) * fee_to_quote_rate) / cost, 8) + return round((fee_cost * fee_to_quote_rate) / cost, 8) def extract_cost_curr_rate(self, fee: Dict, symbol: str, cost: float, amount: float) -> Tuple[float, str, Optional[float]]: diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index bf50167da..b9de212de 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -32,7 +32,8 @@ class Gateio(Exchange): } _ft_has_futures: Dict = { - "needs_trading_fees": True + "needs_trading_fees": True, + "fee_cost_in_contracts": False, # Set explicitly to false for clarity } _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ diff --git a/freqtrade/exchange/okx.py b/freqtrade/exchange/okx.py index 012f51080..afd7a672f 100644 --- a/freqtrade/exchange/okx.py +++ b/freqtrade/exchange/okx.py @@ -28,6 +28,7 @@ class Okx(Exchange): } _ft_has_futures: Dict = { "tickers_have_quoteVolume": False, + "fee_cost_in_contracts": True, } _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 3fd134078..469bfda7e 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1777,7 +1777,6 @@ class FreqtradeBot(LoggingMixin): fee_abs = 0.0 fee_cost = 0.0 trade_base_currency = self.exchange.get_pair_base_currency(trade.pair) - fee_rate_array: List[float] = [] for exectrade in trades: amount += exectrade['amount'] diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 324002685..5f302de71 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -821,7 +821,7 @@ class LocalTrade(): self.open_rate = total_stake / total_amount self.stake_amount = total_stake / (self.leverage or 1.0) self.amount = total_amount - self.fee_open_cost = self.fee_open * self.stake_amount + self.fee_open_cost = self.fee_open * total_stake self.recalc_open_trade_value() if self.stop_loss_pct is not None and self.open_rate is not None: self.adjust_stop_loss(self.open_rate, self.stop_loss_pct) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index f1d430437..6fce0bb8f 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3584,6 +3584,9 @@ def test_extract_cost_curr_rate(mocker, default_conf, order, expected) -> None: 'fee': {'currency': 'POINT', 'cost': 2.0, 'rate': None}}, 1, 4.0), ({'symbol': 'POINT/BTC', 'amount': 0.04, 'cost': 0.5, 'fee': {'currency': 'POINT', 'cost': 2.0, 'rate': None}}, 2, 8.0), + # Missing currency + ({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.05, + 'fee': {'currency': None, 'cost': 0.005}}, None, None), ]) def test_calculate_fee_rate(mocker, default_conf, order, expected, unknown_fee_rate) -> None: mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value={'last': 0.081}) From c98e7ea0558f1093b4ebdeecb8755ff3f60b58fc Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 9 Jul 2022 08:57:15 +0200 Subject: [PATCH 070/220] Revert allowing empty currency for futures --- freqtrade/exchange/exchange.py | 6 +++--- tests/exchange/test_exchange.py | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index fdf323582..cd13964c4 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1616,7 +1616,8 @@ class Exchange: except ccxt.BaseError as e: raise OperationalException(e) from e - def order_has_fee(self, order: Dict) -> bool: + @staticmethod + def order_has_fee(order: Dict) -> bool: """ Verifies if the passed in order dict has the needed keys to extract fees, and that these keys (currency, cost) are not empty. @@ -1627,8 +1628,7 @@ class Exchange: return False return ('fee' in order and order['fee'] is not None and (order['fee'].keys() >= {'currency', 'cost'}) - and (order['fee']['currency'] is not None - or self.trading_mode == TradingMode.FUTURES) + and order['fee']['currency'] is not None and order['fee']['cost'] is not None ) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 6fce0bb8f..acd48b3fd 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3529,10 +3529,8 @@ def test_market_is_active(market, expected_result) -> None: ({'fee': {'currency': 'ETH/BTC', 'cost': None}}, False), ({'fee': {'currency': 'ETH/BTC', 'cost': 0.01}}, True), ]) -def test_order_has_fee(mocker, default_conf, order, expected) -> None: - ex = get_patched_exchange(mocker, default_conf) - - assert ex.order_has_fee(order) == expected +def test_order_has_fee(order, expected) -> None: + assert Exchange.order_has_fee(order) == expected @pytest.mark.parametrize("order,expected", [ From aab59a8cafef0b9236f6bd92a6f0c2b98c7f5232 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 9 Jul 2022 09:00:12 +0200 Subject: [PATCH 071/220] Bump ccxt to required version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2ccadea30..693d408c6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.0 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.89.96 +ccxt==1.90.38 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.2 aiohttp==3.8.1 From ea5f41aa6d5905485c8ca5fbc33702bbfc1bd534 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 10 Jul 2022 09:06:19 +0200 Subject: [PATCH 072/220] Version bump ccxt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 693d408c6..2bce619d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.0 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.90.38 +ccxt==1.90.40 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.2 aiohttp==3.8.1 From 9313a2d294c6e7bf6f114315720ba7092cb81282 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 10 Jul 2022 10:11:39 +0200 Subject: [PATCH 073/220] Update leverage tiers to latest version --- docs/developer.md | 2 +- .../exchange/binance_leverage_tiers.json | 24876 ++++++++-------- 2 files changed, 12845 insertions(+), 12033 deletions(-) diff --git a/docs/developer.md b/docs/developer.md index ce7fb37e1..0209d220a 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -334,7 +334,7 @@ lev_tiers = exchange.fetch_leverage_tiers() # Assumes this is running in the root of the repository. file = Path('freqtrade/exchange/binance_leverage_tiers.json') -json.dump(lev_tiers, file.open('w'), indent=2) +json.dump(dict(sorted(lev_tiers.items())), file.open('w'), indent=2) ``` diff --git a/freqtrade/exchange/binance_leverage_tiers.json b/freqtrade/exchange/binance_leverage_tiers.json index 126b3b62f..1cf6ba079 100644 --- a/freqtrade/exchange/binance_leverage_tiers.json +++ b/freqtrade/exchange/binance_leverage_tiers.json @@ -1,201 +1,87 @@ { - "RAY/USDT": [ + "1000LUNC/BUSD": [ { "tier": 1.0, - "currency": "USDT", + "currency": "BUSD", "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, "info": { "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", + "initialLeverage": "20", + "notionalCap": "25000", "notionalFloor": "0", - "maintMarginRatio": "0.01", + "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", + "currency": "BUSD", "minNotional": 25000.0, "maxNotional": 100000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { - "bracket": "3", + "bracket": "2", "initialLeverage": "10", "notionalCap": "100000", "notionalFloor": "25000", "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "API3/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" + "cum": "625.0" } }, { "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", + "currency": "BUSD", "minNotional": 100000.0, "maxNotional": 250000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { - "bracket": "4", + "bracket": "3", "initialLeverage": "5", "notionalCap": "250000", "notionalFloor": "100000", "maintMarginRatio": "0.1", - "cum": "5700.0" + "cum": "5625.0" } }, { - "tier": 5.0, - "currency": "USDT", + "tier": 4.0, + "currency": "BUSD", "minNotional": 250000.0, "maxNotional": 1000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 2.0, "info": { - "bracket": "5", + "bracket": "4", "initialLeverage": "2", "notionalCap": "1000000", "notionalFloor": "250000", "maintMarginRatio": "0.125", - "cum": "11950.0" + "cum": "11875.0" } }, { - "tier": 6.0, - "currency": "USDT", + "tier": 5.0, + "currency": "BUSD", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { - "bracket": "6", + "bracket": "5", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", - "cum": "386950.0" + "cum": "386875.0" } } ], - "SUSHI/USDT": [ + "1000SHIB/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -296,20 +182,754 @@ "tier": 7.0, "currency": "USDT", "minNotional": 2000000.0, - "maxNotional": 50000000.0, + "maxNotional": 30000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", + "notionalCap": "30000000", "notionalFloor": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } } ], - "CVC/USDT": [ + "1000XEC/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "1INCH/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.012, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.012", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "65.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "690.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5690.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11940.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "10000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386940.0" + } + } + ], + "AAVE/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ADA/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "100000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "500000", + "notionalFloor": "100000", + "maintMarginRatio": "0.05", + "cum": "2500.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 500000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "1000000", + "notionalFloor": "500000", + "maintMarginRatio": "0.1", + "cum": "27500.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "4", + "initialLeverage": "3", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.15", + "cum": "77500.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.25", + "cum": "277500.0" + } + }, + { + "tier": 6.0, + "currency": "BUSD", + "minNotional": 5000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.5", + "cum": "1527500.0" + } + } + ], + "ADA/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.0065, + "maxLeverage": 75.0, + "info": { + "bracket": "1", + "initialLeverage": "75", + "notionalCap": "10000", + "notionalFloor": "0", + "maintMarginRatio": "0.0065", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "2", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "10000", + "maintMarginRatio": "0.01", + "cum": "35.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "3", + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "535.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "4", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8035.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "5", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58035.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "6", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108035.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "7", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.15", + "cum": "233035.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1233035.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 50000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "50000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.5", + "cum": "6233035.0" + } + } + ], + "ALGO/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ALICE/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ALPHA/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -390,6 +1010,2128 @@ "cum": "11950.0" } }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ANC/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "ANKR/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.012, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.012", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "65.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "690.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5690.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11940.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386940.0" + } + } + ], + "ANT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "APE/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "APE/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 150000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "250000", + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "250000", + "maintMarginRatio": "0.1", + "cum": "17000.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": "29500.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.5", + "cum": "654500.0" + } + } + ], + "API3/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "AR/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ARPA/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ATA/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ATOM/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "AUDIO/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "AVAX/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "AVAX/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "7000.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "57000.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "107000.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.25", + "cum": "732000.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.5", + "cum": "3232000.0" + } + } + ], + "AXS/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "2", + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "500.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8000.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58000.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108000.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.1665, + "maxLeverage": 3.0, + "info": { + "bracket": "6", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.1665", + "cum": "315500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 15000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "7", + "initialLeverage": "2", + "notionalCap": "15000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1150500.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 15000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "8", + "initialLeverage": "1", + "notionalCap": "20000000", + "notionalFloor": "15000000", + "maintMarginRatio": "0.5", + "cum": "4900500.0" + } + } + ], + "BAKE/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "BAL/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "BAND/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "BAT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "BCH/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.0065, + "maxLeverage": 75.0, + "info": { + "bracket": "1", + "initialLeverage": "75", + "notionalCap": "10000", + "notionalFloor": "0", + "maintMarginRatio": "0.0065", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "2", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "10000", + "maintMarginRatio": "0.01", + "cum": "35.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "3", + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "535.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "4", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8035.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "5", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58035.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "6", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108035.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "7", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.15", + "cum": "233035.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1233035.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 50000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "50000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.5", + "cum": "6233035.0" + } + } + ], + "BEL/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "BLZ/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, { "tier": 6.0, "currency": "USDT", @@ -407,214 +3149,262 @@ } } ], - "BTS/USDT": [ + "BNB/BUSD": [ { "tier": 1.0, - "currency": "USDT", + "currency": "BUSD", "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, "info": { "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", + "initialLeverage": "20", + "notionalCap": "100000", "notionalFloor": "0", - "maintMarginRatio": "0.01", + "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, "info": { "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" + "initialLeverage": "10", + "notionalCap": "500000", + "notionalFloor": "100000", + "maintMarginRatio": "0.05", + "cum": "2500.0" } }, { "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "currency": "BUSD", + "minNotional": 500000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, "info": { "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" + "initialLeverage": "5", + "notionalCap": "1000000", + "notionalFloor": "500000", + "maintMarginRatio": "0.1", + "cum": "27500.0" } }, { "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, "info": { "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" + "initialLeverage": "3", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.15", + "cum": "77500.0" } }, { "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, + "currency": "BUSD", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.25", + "cum": "277500.0" } }, { "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "currency": "BUSD", + "minNotional": 5000000.0, + "maxNotional": 8000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "notionalCap": "8000000", + "notionalFloor": "5000000", "maintMarginRatio": "0.5", - "cum": "386950.0" + "cum": "1527500.0" } } ], - "HOT/USDT": [ + "BNB/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.0065, + "maxLeverage": 75.0, "info": { "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", + "initialLeverage": "75", + "notionalCap": "10000", "notionalFloor": "0", - "maintMarginRatio": "0.01", + "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2.0, "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, + "minNotional": 10000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, "info": { "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "10000", + "maintMarginRatio": "0.01", + "cum": "35.0" } }, { "tier": 3.0, "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, "info": { "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "535.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, "info": { "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8035.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, "info": { "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58035.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "6", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108035.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "7", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.15", + "cum": "233035.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1233035.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 50000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { - "bracket": "6", + "bracket": "9", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "notionalCap": "50000000", + "notionalFloor": "20000000", "maintMarginRatio": "0.5", - "cum": "386950.0" + "cum": "6233035.0" } } ], - "ZRX/USDT": [ + "BNX/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, - "maxNotional": 5000.0, + "maxNotional": 50000.0, "maintenanceMarginRate": 0.01, "maxLeverage": 50.0, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", + "notionalCap": "50000", "notionalFloor": "0", "maintMarginRatio": "0.01", "cum": "0.0" @@ -623,277 +3413,97 @@ { "tier": 2.0, "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, + "minNotional": 50000.0, + "maxNotional": 150000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "notionalCap": "150000", + "notionalFloor": "50000", "maintMarginRatio": "0.025", - "cum": "75.0" + "cum": "750.0" } }, { "tier": 3.0, "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, + "minNotional": 150000.0, + "maxNotional": 250000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "notionalCap": "250000", + "notionalFloor": "150000", "maintMarginRatio": "0.05", - "cum": "700.0" + "cum": "4500.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, + "minNotional": 250000.0, + "maxNotional": 500000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "notionalCap": "500000", + "notionalFloor": "250000", "maintMarginRatio": "0.1", - "cum": "5700.0" + "cum": "17000.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": "11950.0" + "cum": "29500.0" } }, { "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "QTUM/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, "info": { - "bracket": "5", + "bracket": "6", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" } }, { - "tier": 6.0, + "tier": 7.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "minNotional": 2000000.0, + "maxNotional": 8000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { - "bracket": "6", + "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "notionalCap": "8000000", + "notionalFloor": "2000000", "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "IOTA/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" + "cum": "654500.0" } } ], @@ -1059,7 +3669,479 @@ } } ], - "WAVES/USDT": [ + "BTC/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.004, + "maxLeverage": 125.0, + "info": { + "bracket": "1", + "initialLeverage": "125", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.004", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.005, + "maxLeverage": 100.0, + "info": { + "bracket": "2", + "initialLeverage": "100", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.005", + "cum": "50.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "3", + "initialLeverage": "50", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.01", + "cum": "1300.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "4", + "initialLeverage": "20", + "notionalCap": "10000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.025", + "cum": "16300.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "5", + "initialLeverage": "10", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.05", + "cum": "266300.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 50000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "6", + "initialLeverage": "5", + "notionalCap": "50000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.1", + "cum": "1266300.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 50000000.0, + "maxNotional": 100000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "7", + "initialLeverage": "4", + "notionalCap": "100000000", + "notionalFloor": "50000000", + "maintMarginRatio": "0.125", + "cum": "2516300.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 100000000.0, + "maxNotional": 200000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "8", + "initialLeverage": "3", + "notionalCap": "200000000", + "notionalFloor": "100000000", + "maintMarginRatio": "0.15", + "cum": "5016300.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 200000000.0, + "maxNotional": 300000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "9", + "initialLeverage": "2", + "notionalCap": "300000000", + "notionalFloor": "200000000", + "maintMarginRatio": "0.25", + "cum": "2.50163E7" + } + }, + { + "tier": 10.0, + "currency": "USDT", + "minNotional": 300000000.0, + "maxNotional": 9.223372036854776e+18, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "10", + "initialLeverage": "1", + "notionalCap": "9223372036854775807", + "notionalFloor": "300000000", + "maintMarginRatio": "0.5", + "cum": "1.000163E8" + } + } + ], + "BTCDOM/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "BTCSTUSDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 9.223372036854776e+18, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "9223372036854775807", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "BTCUSDT_220930": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 375000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "375000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 375000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "2000000", + "notionalFloor": "375000", + "maintMarginRatio": "0.05", + "cum": "11250.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 4000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "4000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.1", + "cum": "111250.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 4000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "4", + "initialLeverage": "4", + "notionalCap": "10000000", + "notionalFloor": "4000000", + "maintMarginRatio": "0.125", + "cum": "211250.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "5", + "initialLeverage": "3", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.15", + "cum": "461250.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 40000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "40000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.25", + "cum": "2461250.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 40000000.0, + "maxNotional": 400000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "400000000", + "notionalFloor": "40000000", + "maintMarginRatio": "0.5", + "cum": "1.246125E7" + } + } + ], + "BTS/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -1144,166 +4226,314 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "ADA/USDT": [ + "C98/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", + "initialLeverage": "25", + "notionalCap": "5000", "notionalFloor": "0", - "maintMarginRatio": "0.0065", + "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2.0, "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, "info": { "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" } }, { "tier": 3.0, "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, "info": { "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, "info": { "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, "info": { "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" } }, { "tier": 6.0, "currency": "USDT", - "minNotional": 2000000.0, + "minNotional": 1000000.0, "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "6", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { - "bracket": "9", + "bracket": "6", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "notionalCap": "5000000", + "notionalFloor": "1000000", "maintMarginRatio": "0.5", - "cum": "6233035.0" + "cum": "386950.0" } } ], - "LIT/USDT": [ + "CELO/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "CELR/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "CHR/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -1388,312 +4618,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "XTZ/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, - "info": { - "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", - "maintMarginRatio": "0.0065", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "6", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6233035.0" - } - } - ], - "BNB/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, - "info": { - "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", - "maintMarginRatio": "0.0065", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "6", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6233035.0" - } - } - ], - "AKRO/USDT": [ + "CHZ/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -1791,6 +4729,610 @@ } } ], + "COMP/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "COTI/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "CRV/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 150000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "250000", + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "250000", + "maintMarginRatio": "0.1", + "cum": "17000.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": "29500.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.5", + "cum": "654500.0" + } + } + ], + "CTK/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "CTSI/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "CVC/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], "DAR/USDT": [ { "tier": 1.0, @@ -1876,20 +5418,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "HNT/USDT": [ + "DASH/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -1974,19 +5516,1503 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], + "DEFI/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "DENT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "DGB/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "DODO/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "DOGE/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "100000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "500000", + "notionalFloor": "100000", + "maintMarginRatio": "0.05", + "cum": "2500.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 500000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "1000000", + "notionalFloor": "500000", + "maintMarginRatio": "0.1", + "cum": "27500.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "4", + "initialLeverage": "3", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.15", + "cum": "77500.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.25", + "cum": "277500.0" + } + }, + { + "tier": 6.0, + "currency": "BUSD", + "minNotional": 5000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.5", + "cum": "1527500.0" + } + } + ], + "DOGE/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "7000.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "57000.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "107000.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.25", + "cum": "732000.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.5", + "cum": "3232000.0" + } + } + ], + "DOT/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 30000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "30000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "DOT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.0065, + "maxLeverage": 75.0, + "info": { + "bracket": "1", + "initialLeverage": "75", + "notionalCap": "10000", + "notionalFloor": "0", + "maintMarginRatio": "0.0065", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "2", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "10000", + "maintMarginRatio": "0.01", + "cum": "35.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "3", + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "535.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "4", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8035.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "5", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58035.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "6", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108035.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "7", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.15", + "cum": "233035.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 50000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "50000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1233035.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 50000000.0, + "maxNotional": 100000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "100000000", + "notionalFloor": "50000000", + "maintMarginRatio": "0.5", + "cum": "1.3733035E7" + } + } + ], + "DUSK/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "DYDX/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 150000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "250000", + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "250000", + "maintMarginRatio": "0.1", + "cum": "17000.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": "29500.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 4000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "4000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 4000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "4000000", + "maintMarginRatio": "0.5", + "cum": "1154500.0" + } + } + ], + "EGLD/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 50000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "50000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ENJ/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 150000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "250000", + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "250000", + "maintMarginRatio": "0.1", + "cum": "17000.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": "29500.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.5", + "cum": "654500.0" + } + } + ], + "ENS/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "EOS/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.0065, + "maxLeverage": 75.0, + "info": { + "bracket": "1", + "initialLeverage": "75", + "notionalCap": "10000", + "notionalFloor": "0", + "maintMarginRatio": "0.0065", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "2", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "10000", + "maintMarginRatio": "0.01", + "cum": "35.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "3", + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "535.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "4", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8035.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "5", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58035.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "6", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108035.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "7", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.15", + "cum": "233035.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1233035.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 50000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "50000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.5", + "cum": "6233035.0" + } + } + ], "ETC/USDT": [ { "tier": 1.0, @@ -2133,345 +7159,165 @@ } } ], - "XMR/USDT": [ + "ETH/BUSD": [ { "tier": 1.0, - "currency": "USDT", + "currency": "BUSD", "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.004, + "maxLeverage": 50.0, "info": { "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", + "initialLeverage": "50", + "notionalCap": "25000", "notionalFloor": "0", - "maintMarginRatio": "0.0065", + "maintMarginRatio": "0.004", "cum": "0.0" } }, { "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.005, + "maxLeverage": 25.0, "info": { "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" + "initialLeverage": "25", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.005", + "cum": "25.0" } }, { "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 20.0, "info": { "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" + "initialLeverage": "20", + "notionalCap": "500000", + "notionalFloor": "100000", + "maintMarginRatio": "0.01", + "cum": "525.0" } }, { "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, + "currency": "BUSD", + "minNotional": 500000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.025, "maxLeverage": 10.0, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" + "notionalCap": "1500000", + "notionalFloor": "500000", + "maintMarginRatio": "0.025", + "cum": "8025.0" } }, { "tier": 5.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, + "currency": "BUSD", + "minNotional": 1500000.0, + "maxNotional": 4000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 6.0, "info": { "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" + "initialLeverage": "6", + "notionalCap": "4000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.05", + "cum": "45525.0" } }, { "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, + "currency": "BUSD", + "minNotional": 4000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, "info": { "bracket": "6", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" + "initialLeverage": "5", + "notionalCap": "10000000", + "notionalFloor": "4000000", + "maintMarginRatio": "0.1", + "cum": "245525.0" } }, { "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, + "currency": "BUSD", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, "info": { "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" + "initialLeverage": "4", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.125", + "cum": "495525.0" } }, { "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, + "currency": "BUSD", + "minNotional": 20000000.0, + "maxNotional": 40000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, "info": { "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" + "initialLeverage": "3", + "notionalCap": "40000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.15", + "cum": "995525.0" } }, { "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6233035.0" - } - } - ], - "YFI/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "FTT/BUSD": [ - { - "tier": 1.0, "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", - "maintMarginRatio": "0.025", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", - "maintMarginRatio": "0.05", - "cum": "2500.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 500000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", - "maintMarginRatio": "0.1", - "cum": "27500.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "4", - "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.15", - "cum": "77500.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, + "minNotional": 40000000.0, + "maxNotional": 150000000.0, "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, "info": { - "bracket": "5", + "bracket": "9", "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "notionalCap": "150000000", + "notionalFloor": "40000000", "maintMarginRatio": "0.25", - "cum": "277500.0" + "cum": "4995525.0" } }, { - "tier": 6.0, + "tier": 10.0, "currency": "BUSD", - "minNotional": 5000000.0, - "maxNotional": 30000000.0, + "minNotional": 150000000.0, + "maxNotional": 500000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { - "bracket": "6", + "bracket": "10", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", + "notionalCap": "500000000", + "notionalFloor": "150000000", "maintMarginRatio": "0.5", - "cum": "1527500.0" + "cum": "4.2495525E7" } } ], @@ -2637,7 +7483,1281 @@ } } ], - "ALICE/USDT": [ + "ETHUSDT_220930": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 375000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "375000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 375000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "2000000", + "notionalFloor": "375000", + "maintMarginRatio": "0.05", + "cum": "11250.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 4000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "4000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.1", + "cum": "111250.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 4000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "4", + "initialLeverage": "4", + "notionalCap": "10000000", + "notionalFloor": "4000000", + "maintMarginRatio": "0.125", + "cum": "211250.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "5", + "initialLeverage": "3", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.15", + "cum": "461250.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 40000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "40000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.25", + "cum": "2461250.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 40000000.0, + "maxNotional": 400000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "400000000", + "notionalFloor": "40000000", + "maintMarginRatio": "0.5", + "cum": "1.246125E7" + } + } + ], + "FIL/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "2", + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "500.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8000.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58000.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108000.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.1665, + "maxLeverage": 3.0, + "info": { + "bracket": "6", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.1665", + "cum": "315500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "7", + "initialLeverage": "2", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1150500.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 30000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "8", + "initialLeverage": "1", + "notionalCap": "30000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.5", + "cum": "6150500.0" + } + } + ], + "FLM/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "10000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "FLOW/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "FTM/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "FTM/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 150000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "250000", + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "250000", + "maintMarginRatio": "0.1", + "cum": "17000.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": "29500.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 4000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "4000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 4000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "4000000", + "maintMarginRatio": "0.5", + "cum": "1154500.0" + } + } + ], + "FTT/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "100000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "500000", + "notionalFloor": "100000", + "maintMarginRatio": "0.05", + "cum": "2500.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 500000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "1000000", + "notionalFloor": "500000", + "maintMarginRatio": "0.1", + "cum": "27500.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "4", + "initialLeverage": "3", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.15", + "cum": "77500.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.25", + "cum": "277500.0" + } + }, + { + "tier": 6.0, + "currency": "BUSD", + "minNotional": 5000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.5", + "cum": "1527500.0" + } + } + ], + "FTT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "GAL/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "GAL/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "GALA/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "GALA/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "GMT/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "GMT/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -2751,7 +8871,579 @@ } } ], - "ALPHA/USDT": [ + "GRT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "GTC/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "HBAR/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "HNT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "HOT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ICP/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 30000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "30000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "ICP/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -2849,7 +9541,105 @@ } } ], - "WOO/USDT": [ + "ICX/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "IMX/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -2934,20 +9724,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "SFP/USDT": [ + "IOST/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -3032,13 +9822,3425 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "IOTA/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "IOTX/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "JASMY/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "KAVA/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "KLAY/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "KNC/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "KSM/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "LINA/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "LINK/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "LINK/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.0065, + "maxLeverage": 75.0, + "info": { + "bracket": "1", + "initialLeverage": "75", + "notionalCap": "10000", + "notionalFloor": "0", + "maintMarginRatio": "0.0065", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "2", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "10000", + "maintMarginRatio": "0.01", + "cum": "35.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "3", + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "535.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "4", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8035.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "5", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58035.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "6", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108035.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "7", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.15", + "cum": "233035.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1233035.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 50000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "50000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.5", + "cum": "6233035.0" + } + } + ], + "LIT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "LPT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "LRC/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "LTC/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "LTC/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.0065, + "maxLeverage": 75.0, + "info": { + "bracket": "1", + "initialLeverage": "75", + "notionalCap": "10000", + "notionalFloor": "0", + "maintMarginRatio": "0.0065", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "2", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "10000", + "maintMarginRatio": "0.01", + "cum": "35.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "3", + "initialLeverage": "25", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "535.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "4", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8035.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "5", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58035.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "6", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108035.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "7", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.15", + "cum": "233035.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1233035.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 50000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "50000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.5", + "cum": "6233035.0" + } + } + ], + "LUNA2/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "MANA/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 150000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "250000", + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "250000", + "maintMarginRatio": "0.1", + "cum": "17000.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": "29500.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.5", + "cum": "654500.0" + } + } + ], + "MASK/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "MATIC/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 150000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "250000", + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "250000", + "maintMarginRatio": "0.1", + "cum": "17000.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "29500.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "123250.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "373250.0" + } + } + ], + "MKR/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "MTL/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "NEAR/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "NEAR/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "50000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 150000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "250000", + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "250000", + "maintMarginRatio": "0.1", + "cum": "17000.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": "29500.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.5", + "cum": "654500.0" + } + } + ], + "NEO/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "NKN/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "OCEAN/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "OGN/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "OMG/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ONE/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "ONT/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "OP/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 8000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "8000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "PEOPLE/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "QTUM/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "RAY/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" @@ -3130,20 +13332,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "BAT/USDT": [ + "REN/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -3228,279 +13430,19 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "DOGE/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "7000.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "57000.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "5", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "107000.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.25", - "cum": "732000.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.5", - "cum": "3232000.0" - } - } - ], - "TRX/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, - "info": { - "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", - "maintMarginRatio": "0.0065", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "6", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6233035.0" - } - } - ], "RLC/USDT": [ { "tier": 1.0, @@ -3586,820 +13528,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "BTCSTUSDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 9.223372036854776e+18, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "9223372036854775807", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "STORJ/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "SNX/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "1000XEC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "AUDIO/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "NEAR/BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "0", - "maintMarginRatio": "0.025", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "625.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5625.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "4", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11875.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "5", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386875.0" - } - } - ], - "XLM/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, - "info": { - "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", - "maintMarginRatio": "0.0065", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, "info": { "bracket": "6", - "initialLeverage": "4", + "initialLeverage": "1", "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6233035.0" - } - } - ], - "APE/BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "0", - "maintMarginRatio": "0.025", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "625.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5625.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "4", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11875.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "5", - "initialLeverage": "1", - "notionalCap": "30000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", - "cum": "386875.0" + "cum": "386950.0" } } ], - "IOTX/USDT": [ + "ROSE/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -4484,438 +13626,30 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "NEO/USDT": [ + "RSR/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "UNFI/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "SAND/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "DASH/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "KAVA/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", + "initialLeverage": "25", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.01", @@ -5101,121 +13835,7 @@ } } ], - "APE/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "CTK/USDT": [ + "RVN/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -5300,394 +13920,216 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "LINK/USDT": [ + "SAND/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "SAND/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, "info": { "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", + "initialLeverage": "50", + "notionalCap": "50000", "notionalFloor": "0", - "maintMarginRatio": "0.0065", + "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2.0, "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "minNotional": 50000.0, + "maxNotional": 150000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, "info": { "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" + "initialLeverage": "20", + "notionalCap": "150000", + "notionalFloor": "50000", + "maintMarginRatio": "0.025", + "cum": "750.0" } }, { "tier": 3.0, "currency": "USDT", - "minNotional": 50000.0, + "minNotional": 150000.0, "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, "info": { "bracket": "3", - "initialLeverage": "25", + "initialLeverage": "10", "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" + "notionalFloor": "150000", + "maintMarginRatio": "0.05", + "cum": "4500.0" } }, { "tier": 4.0, "currency": "USDT", "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, "info": { "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", + "initialLeverage": "5", + "notionalCap": "500000", "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" + "maintMarginRatio": "0.1", + "cum": "17000.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, + "minNotional": 500000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, "info": { "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" + "initialLeverage": "4", + "notionalCap": "1000000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "29500.0" } }, { "tier": 6.0, "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.25", + "cum": "154500.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", "minNotional": 2000000.0, "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, "info": { - "bracket": "6", - "initialLeverage": "4", + "bracket": "7", + "initialLeverage": "1", "notionalCap": "5000000", "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6233035.0" - } - } - ], - "CELR/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } } ], - "BNX/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "RSR/USDT": [ + "SC/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -5772,118 +14214,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "ADA/BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", - "maintMarginRatio": "0.025", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", - "maintMarginRatio": "0.05", - "cum": "2500.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 500000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", - "maintMarginRatio": "0.1", - "cum": "27500.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "4", - "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.15", - "cum": "77500.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.25", - "cum": "277500.0" - } - }, - { - "tier": 6.0, - "currency": "BUSD", - "minNotional": 5000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.5", - "cum": "1527500.0" - } - } - ], - "DGB/USDT": [ + "SFP/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -5968,13 +14312,13 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" @@ -6066,666 +14410,30 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "REN/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "LPT/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "JASMY/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "TOMO/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "MTL/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "LTC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, - "info": { - "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", - "maintMarginRatio": "0.0065", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, "info": { "bracket": "6", - "initialLeverage": "4", + "initialLeverage": "1", "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "notionalFloor": "1000000", "maintMarginRatio": "0.5", - "cum": "6233035.0" + "cum": "386950.0" } } ], - "DODO/USDT": [ + "SNX/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "50", + "initialLeverage": "25", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.01", @@ -6800,3185 +14508,19 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "EGLD/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "KSM/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "BNB/BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", - "maintMarginRatio": "0.025", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", - "maintMarginRatio": "0.05", - "cum": "2500.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 500000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", - "maintMarginRatio": "0.1", - "cum": "27500.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "4", - "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.15", - "cum": "77500.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 2000000.0, "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, "info": { - "bracket": "5", - "initialLeverage": "2", + "bracket": "6", + "initialLeverage": "1", "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.25", - "cum": "277500.0" - } - }, - { - "tier": 6.0, - "currency": "BUSD", - "minNotional": 5000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.5", - "cum": "1527500.0" - } - } - ], - "ONT/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "VET/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "IMX/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "TRB/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "MANA/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "FLOW/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "COTI/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "CHR/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "BAKE/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "AVAX/BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "0", - "maintMarginRatio": "0.025", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "625.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5625.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "4", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11875.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "5", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386875.0" - } - } - ], - "GRT/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "FLM/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "GAL/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "MASK/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "EOS/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, - "info": { - "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", - "maintMarginRatio": "0.0065", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "6", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6233035.0" - } - } - ], - "OGN/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "SC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ETHUSDT_220624": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 375000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "375000", - "notionalFloor": "0", - "maintMarginRatio": "0.02", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 375000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "2000000", - "notionalFloor": "375000", - "maintMarginRatio": "0.05", - "cum": "11250.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 4000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "4000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.1", - "cum": "111250.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 4000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "4", - "initialLeverage": "4", - "notionalCap": "10000000", - "notionalFloor": "4000000", - "maintMarginRatio": "0.125", - "cum": "211250.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "5", - "initialLeverage": "3", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.15", - "cum": "461250.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 40000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "40000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.25", - "cum": "2461250.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 40000000.0, - "maxNotional": 400000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "400000000", - "notionalFloor": "40000000", - "maintMarginRatio": "0.5", - "cum": "1.246125E7" - } - } - ], - "BAL/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "STMX/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "DENT/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "KNC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "SRM/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ENJ/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "C98/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ZEN/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ATOM/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "NEAR/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], "SOL/BUSD": [ { "tier": 1.0, @@ -10064,1812 +14606,20 @@ "tier": 6.0, "currency": "BUSD", "minNotional": 5000000.0, - "maxNotional": 30000000.0, + "maxNotional": 8000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "8000000", "notionalFloor": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" } } ], - "ENS/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "BCH/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, - "info": { - "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", - "maintMarginRatio": "0.0065", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8035.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "5", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58035.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "6", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108035.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "9", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6233035.0" - } - } - ], - "ATA/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "IOST/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "HBAR/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ZEC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "1000SHIB/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "TLM/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ANT/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ETH/BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.004, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "25000", - "notionalFloor": "0", - "maintMarginRatio": "0.004", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.005, - "maxLeverage": 25.0, - "info": { - "bracket": "2", - "initialLeverage": "25", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.005", - "cum": "25.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 20.0, - "info": { - "bracket": "3", - "initialLeverage": "20", - "notionalCap": "500000", - "notionalFloor": "100000", - "maintMarginRatio": "0.01", - "cum": "525.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 500000.0, - "maxNotional": 1500000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 10.0, - "info": { - "bracket": "4", - "initialLeverage": "10", - "notionalCap": "1500000", - "notionalFloor": "500000", - "maintMarginRatio": "0.025", - "cum": "8025.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 1500000.0, - "maxNotional": 4000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 6.0, - "info": { - "bracket": "5", - "initialLeverage": "6", - "notionalCap": "4000000", - "notionalFloor": "1500000", - "maintMarginRatio": "0.05", - "cum": "45525.0" - } - }, - { - "tier": 6.0, - "currency": "BUSD", - "minNotional": 4000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "6", - "initialLeverage": "5", - "notionalCap": "10000000", - "notionalFloor": "4000000", - "maintMarginRatio": "0.1", - "cum": "245525.0" - } - }, - { - "tier": 7.0, - "currency": "BUSD", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "7", - "initialLeverage": "4", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.125", - "cum": "495525.0" - } - }, - { - "tier": 8.0, - "currency": "BUSD", - "minNotional": 20000000.0, - "maxNotional": 40000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "8", - "initialLeverage": "3", - "notionalCap": "40000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.15", - "cum": "995525.0" - } - }, - { - "tier": 9.0, - "currency": "BUSD", - "minNotional": 40000000.0, - "maxNotional": 150000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "9", - "initialLeverage": "2", - "notionalCap": "150000000", - "notionalFloor": "40000000", - "maintMarginRatio": "0.25", - "cum": "4995525.0" - } - }, - { - "tier": 10.0, - "currency": "BUSD", - "minNotional": 150000000.0, - "maxNotional": 500000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "10", - "initialLeverage": "1", - "notionalCap": "500000000", - "notionalFloor": "150000000", - "maintMarginRatio": "0.5", - "cum": "4.2495525E7" - } - } - ], - "GALA/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "AAVE/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "2", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "500.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8000.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58000.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "5", - "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108000.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.1665, - "maxLeverage": 3.0, - "info": { - "bracket": "6", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.1665", - "cum": "315500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "7", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1150500.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "8", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6150500.0" - } - } - ], - "GTC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ALGO/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "ICP/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "LRC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "AVAX/USDT": [ + "SOL/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -11970,526 +14720,20 @@ "tier": 7.0, "currency": "USDT", "minNotional": 10000000.0, - "maxNotional": 50000000.0, + "maxNotional": 20000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", + "notionalCap": "20000000", "notionalFloor": "10000000", "maintMarginRatio": "0.5", "cum": "3232000.0" } } ], - "ARPA/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "CELO/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "ROSE/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "MATIC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 500000.0, - "maxNotional": 750000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "5", - "initialLeverage": "4", - "notionalCap": "750000", - "notionalFloor": "500000", - "maintMarginRatio": "0.125", - "cum": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 750000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "750000", - "maintMarginRatio": "0.25", - "cum": "123250.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "373250.0" - } - } - ], - "1INCH/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.012, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.012", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "65.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "690.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5690.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11940.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 100000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "100000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386940.0" - } - } - ], - "MKR/USDT": [ + "SRM/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -12574,20 +14818,216 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "PEOPLE/USDT": [ + "STMX/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "STORJ/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "SUSHI/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -12672,13 +15112,111 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "SXP/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" @@ -12802,31 +15340,733 @@ "tier": 8.0, "currency": "USDT", "minNotional": 20000000.0, - "maxNotional": 50000000.0, + "maxNotional": 30000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "8", "initialLeverage": "1", - "notionalCap": "50000000", + "notionalCap": "30000000", "notionalFloor": "20000000", "maintMarginRatio": "0.5", "cum": "6150500.0" } } ], + "TLM/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 30000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "30000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "TLM/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "TOMO/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "TRB/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 30000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "30000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], + "TRX/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "TRX/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.0065, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "10000", + "notionalFloor": "0", + "maintMarginRatio": "0.0065", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 50000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 22.0, + "info": { + "bracket": "2", + "initialLeverage": "22", + "notionalCap": "50000", + "notionalFloor": "10000", + "maintMarginRatio": "0.01", + "cum": "35.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 50000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 20.0, + "info": { + "bracket": "3", + "initialLeverage": "20", + "notionalCap": "250000", + "notionalFloor": "50000", + "maintMarginRatio": "0.02", + "cum": "535.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "4", + "initialLeverage": "10", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.05", + "cum": "8035.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 2000000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "5", + "initialLeverage": "5", + "notionalCap": "2000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.1", + "cum": "58035.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 2000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "6", + "initialLeverage": "4", + "notionalCap": "5000000", + "notionalFloor": "2000000", + "maintMarginRatio": "0.125", + "cum": "108035.0" + } + }, + { + "tier": 7.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.15, + "maxLeverage": 3.0, + "info": { + "bracket": "7", + "initialLeverage": "3", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.15", + "cum": "233035.0" + } + }, + { + "tier": 8.0, + "currency": "USDT", + "minNotional": 10000000.0, + "maxNotional": 20000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "20000000", + "notionalFloor": "10000000", + "maintMarginRatio": "0.25", + "cum": "1233035.0" + } + }, + { + "tier": 9.0, + "currency": "USDT", + "minNotional": 20000000.0, + "maxNotional": 30000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "30000000", + "notionalFloor": "20000000", + "maintMarginRatio": "0.5", + "cum": "6233035.0" + } + } + ], + "UNFI/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], "UNI/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, - "maxNotional": 50000.0, + "maxNotional": 5000.0, "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", + "initialLeverage": "25", + "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.01", "cum": "0.0" @@ -12835,215 +16075,85 @@ { "tier": 2.0, "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, "info": { "bracket": "2", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "500.0" + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" } }, { "tier": 3.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, + "minNotional": 25000.0, + "maxNotional": 100000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "notionalCap": "100000", + "notionalFloor": "25000", "maintMarginRatio": "0.05", - "cum": "8000.0" + "cum": "700.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, + "minNotional": 100000.0, + "maxNotional": 250000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "notionalCap": "250000", + "notionalFloor": "100000", "maintMarginRatio": "0.1", - "cum": "58000.0" + "cum": "5700.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 2000000.0, + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, "info": { - "bracket": "5", - "initialLeverage": "4", + "bracket": "6", + "initialLeverage": "1", "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108000.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.1665, - "maxLeverage": 3.0, - "info": { - "bracket": "6", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.1665", - "cum": "315500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "7", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1150500.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "8", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.5", - "cum": "6150500.0" - } - } - ], - "LINA/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "AR/USDT": [ + "VET/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -13128,248 +16238,102 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "RVN/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "FIL/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "2", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "500.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8000.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58000.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 2000000.0, "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, "info": { - "bracket": "5", - "initialLeverage": "4", + "bracket": "6", + "initialLeverage": "1", "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108000.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.1665, - "maxLeverage": 3.0, - "info": { - "bracket": "6", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.1665", - "cum": "315500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "7", - "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1150500.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "8", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "notionalFloor": "1000000", "maintMarginRatio": "0.5", - "cum": "6150500.0" + "cum": "386950.0" } } ], - "NKN/USDT": [ + "WAVES/BUSD": [ + { + "tier": 1.0, + "currency": "BUSD", + "minNotional": 0.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "1", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "0", + "maintMarginRatio": "0.025", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "BUSD", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "2", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "625.0" + } + }, + { + "tier": 3.0, + "currency": "BUSD", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "3", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5625.0" + } + }, + { + "tier": 4.0, + "currency": "BUSD", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "4", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11875.0" + } + }, + { + "tier": 5.0, + "currency": "BUSD", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "5", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386875.0" + } + } + ], + "WAVES/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -13454,20 +16418,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "KLAY/USDT": [ + "WOO/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -13552,20 +16516,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "DEFI/USDT": [ + "XEM/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -13650,216 +16614,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "COMP/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "BTCDOM/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "SOL/USDT": [ + "XLM/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -13960,590 +16728,20 @@ "tier": 7.0, "currency": "USDT", "minNotional": 10000000.0, - "maxNotional": 50000000.0, + "maxNotional": 20000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", + "notionalCap": "20000000", "notionalFloor": "10000000", "maintMarginRatio": "0.5", "cum": "3232000.0" } } ], - "BTC/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.004, - "maxLeverage": 125.0, - "info": { - "bracket": "1", - "initialLeverage": "125", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.004", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.005, - "maxLeverage": 100.0, - "info": { - "bracket": "2", - "initialLeverage": "100", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.005", - "cum": "50.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "3", - "initialLeverage": "50", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.01", - "cum": "1300.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "4", - "initialLeverage": "20", - "notionalCap": "10000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.025", - "cum": "16300.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "5", - "initialLeverage": "10", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.05", - "cum": "266300.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "6", - "initialLeverage": "5", - "notionalCap": "50000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.1", - "cum": "1266300.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 50000000.0, - "maxNotional": 100000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "7", - "initialLeverage": "4", - "notionalCap": "100000000", - "notionalFloor": "50000000", - "maintMarginRatio": "0.125", - "cum": "2516300.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 100000000.0, - "maxNotional": 200000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "8", - "initialLeverage": "3", - "notionalCap": "200000000", - "notionalFloor": "100000000", - "maintMarginRatio": "0.15", - "cum": "5016300.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 200000000.0, - "maxNotional": 300000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "9", - "initialLeverage": "2", - "notionalCap": "300000000", - "notionalFloor": "200000000", - "maintMarginRatio": "0.25", - "cum": "2.50163E7" - } - }, - { - "tier": 10.0, - "currency": "USDT", - "minNotional": 300000000.0, - "maxNotional": 9.223372036854776e+18, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "10", - "initialLeverage": "1", - "notionalCap": "9223372036854775807", - "notionalFloor": "300000000", - "maintMarginRatio": "0.5", - "cum": "1.000163E8" - } - } - ], - "OMG/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.024, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.024", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "5.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "630.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5630.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11880.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "10000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386880.0" - } - } - ], - "ICX/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "BLZ/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "GMT/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "FTM/USDT": [ + "XMR/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -14644,117 +16842,19 @@ "tier": 7.0, "currency": "USDT", "minNotional": 10000000.0, - "maxNotional": 50000000.0, + "maxNotional": 20000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", + "notionalCap": "20000000", "notionalFloor": "10000000", "maintMarginRatio": "0.5", "cum": "3232000.0" } } ], - "BAND/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], "XRP/BUSD": [ { "tier": 1.0, @@ -14840,111 +16940,13 @@ "tier": 6.0, "currency": "BUSD", "minNotional": 5000000.0, - "maxNotional": 30000000.0, + "maxNotional": 8000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.5", - "cum": "1527500.0" - } - } - ], - "DOGE/BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", - "maintMarginRatio": "0.025", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", - "maintMarginRatio": "0.05", - "cum": "2500.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 500000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", - "maintMarginRatio": "0.1", - "cum": "27500.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "4", - "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.15", - "cum": "77500.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 2000000.0, - "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.25", - "cum": "277500.0" - } - }, - { - "tier": 6.0, - "currency": "BUSD", - "minNotional": 5000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "8000000", "notionalFloor": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" @@ -15097,203 +17099,7 @@ } } ], - "FTT/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "SXP/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "CRV/USDT": [ + "XTZ/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -15314,13 +17120,13 @@ "tier": 2.0, "currency": "USDT", "minNotional": 50000.0, - "maxNotional": 150000.0, + "maxNotional": 250000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", + "notionalCap": "250000", "notionalFloor": "50000", "maintMarginRatio": "0.025", "cum": "750.0" @@ -15329,329 +17135,85 @@ { "tier": 3.0, "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "BEL/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "DOT/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 10000.0, - "maintenanceMarginRate": 0.0065, - "maxLeverage": 75.0, - "info": { - "bracket": "1", - "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", - "maintMarginRatio": "0.0065", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 10000.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "2", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", - "maintMarginRatio": "0.01", - "cum": "35.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "3", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "535.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", "minNotional": 250000.0, "maxNotional": 1000000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { - "bracket": "4", + "bracket": "3", "initialLeverage": "10", "notionalCap": "1000000", "notionalFloor": "250000", "maintMarginRatio": "0.05", - "cum": "8035.0" + "cum": "7000.0" } }, { - "tier": 5.0, + "tier": 4.0, "currency": "USDT", "minNotional": 1000000.0, "maxNotional": 2000000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { - "bracket": "5", + "bracket": "4", "initialLeverage": "5", "notionalCap": "2000000", "notionalFloor": "1000000", "maintMarginRatio": "0.1", - "cum": "58035.0" + "cum": "57000.0" } }, { - "tier": 6.0, + "tier": 5.0, "currency": "USDT", "minNotional": 2000000.0, "maxNotional": 5000000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, "info": { - "bracket": "6", + "bracket": "5", "initialLeverage": "4", "notionalCap": "5000000", "notionalFloor": "2000000", "maintMarginRatio": "0.125", - "cum": "108035.0" + "cum": "107000.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 5000000.0, + "maxNotional": 10000000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "10000000", + "notionalFloor": "5000000", + "maintMarginRatio": "0.25", + "cum": "732000.0" } }, { "tier": 7.0, "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "7", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.15", - "cum": "233035.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", "minNotional": 10000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "8", - "initialLeverage": "2", - "notionalCap": "50000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1233035.0" - } - }, - { - "tier": 9.0, - "currency": "USDT", - "minNotional": 50000000.0, - "maxNotional": 100000000.0, + "maxNotional": 20000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { - "bracket": "9", + "bracket": "7", "initialLeverage": "1", - "notionalCap": "100000000", - "notionalFloor": "50000000", + "notionalCap": "20000000", + "notionalFloor": "10000000", "maintMarginRatio": "0.5", - "cum": "1.3733035E7" + "cum": "3232000.0" } } ], - "XEM/USDT": [ + "YFI/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -15736,102 +17298,20 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "GMT/BUSD": [ - { - "tier": 1.0, - "currency": "BUSD", - "minNotional": 0.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "1", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "0", - "maintMarginRatio": "0.025", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "BUSD", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "625.0" - } - }, - { - "tier": 3.0, - "currency": "BUSD", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5625.0" - } - }, - { - "tier": 4.0, - "currency": "BUSD", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "4", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11875.0" - } - }, - { - "tier": 5.0, - "currency": "BUSD", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "5", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386875.0" - } - } - ], - "ONE/USDT": [ + "ZEC/USDT": [ { "tier": 1.0, "currency": "USDT", @@ -15932,31 +17412,129 @@ "tier": 7.0, "currency": "USDT", "minNotional": 2000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } } ], + "ZEN/USDT": [ + { + "tier": 1.0, + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 50.0, + "info": { + "bracket": "1", + "initialLeverage": "50", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "75.0" + } + }, + { + "tier": 3.0, + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 100000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "100000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "700.0" + } + }, + { + "tier": 4.0, + "currency": "USDT", + "minNotional": 100000.0, + "maxNotional": 250000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "250000", + "notionalFloor": "100000", + "maintMarginRatio": "0.1", + "cum": "5700.0" + } + }, + { + "tier": 5.0, + "currency": "USDT", + "minNotional": 250000.0, + "maxNotional": 1000000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 2.0, + "info": { + "bracket": "5", + "initialLeverage": "2", + "notionalCap": "1000000", + "notionalFloor": "250000", + "maintMarginRatio": "0.125", + "cum": "11950.0" + } + }, + { + "tier": 6.0, + "currency": "USDT", + "minNotional": 1000000.0, + "maxNotional": 5000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "6", + "initialLeverage": "1", + "notionalCap": "5000000", + "notionalFloor": "1000000", + "maintMarginRatio": "0.5", + "cum": "386950.0" + } + } + ], "ZIL/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, - "maxNotional": 50000.0, + "maxNotional": 5000.0, "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", + "initialLeverage": "25", + "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.01", "cum": "0.0" @@ -15965,649 +17543,95 @@ { "tier": 2.0, "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, + "minNotional": 5000.0, + "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, "maxLeverage": 20.0, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "notionalCap": "25000", + "notionalFloor": "5000", "maintMarginRatio": "0.025", - "cum": "750.0" + "cum": "75.0" } }, { "tier": 3.0, "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, + "minNotional": 25000.0, + "maxNotional": 100000.0, "maintenanceMarginRate": 0.05, "maxLeverage": 10.0, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "notionalCap": "100000", + "notionalFloor": "25000", "maintMarginRatio": "0.05", - "cum": "4500.0" + "cum": "700.0" } }, { "tier": 4.0, "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, + "minNotional": 100000.0, + "maxNotional": 250000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "notionalCap": "250000", + "notionalFloor": "100000", "maintMarginRatio": "0.1", - "cum": "17000.0" + "cum": "5700.0" } }, { "tier": 5.0, "currency": "USDT", - "minNotional": 500000.0, + "minNotional": 250000.0, "maxNotional": 1000000.0, "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, + "maxLeverage": 2.0, "info": { "bracket": "5", - "initialLeverage": "4", + "initialLeverage": "2", "notionalCap": "1000000", - "notionalFloor": "500000", + "notionalFloor": "250000", "maintMarginRatio": "0.125", - "cum": "29500.0" + "cum": "11950.0" } }, { "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.5", - "cum": "654500.0" - } - } - ], - "AXS/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "2", - "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", - "maintMarginRatio": "0.02", - "cum": "500.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.05", - "cum": "8000.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.1", - "cum": "58000.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 2000000.0, "maxNotional": 5000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, "info": { - "bracket": "5", - "initialLeverage": "4", + "bracket": "6", + "initialLeverage": "1", "notionalCap": "5000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.125", - "cum": "108000.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 5000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.1665, - "maxLeverage": 3.0, - "info": { - "bracket": "6", - "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", - "maintMarginRatio": "0.1665", - "cum": "315500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 15000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "7", - "initialLeverage": "2", - "notionalCap": "15000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.25", - "cum": "1150500.0" - } - }, - { - "tier": 8.0, - "currency": "USDT", - "minNotional": 15000000.0, - "maxNotional": 50000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "8", - "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "15000000", - "maintMarginRatio": "0.5", - "cum": "4900500.0" - } - } - ], - "DYDX/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 50000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "50000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 50000.0, - "maxNotional": 150000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", - "maintMarginRatio": "0.025", - "cum": "750.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 150000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", - "maintMarginRatio": "0.05", - "cum": "4500.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 500000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", - "maintMarginRatio": "0.1", - "cum": "17000.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": "29500.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 4000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "4000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.25", - "cum": "154500.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 4000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "4000000", - "maintMarginRatio": "0.5", - "cum": "1154500.0" - } - } - ], - "OCEAN/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } } ], - "CHZ/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.012, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.012", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "65.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "690.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5690.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11940.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386940.0" - } - } - ], - "ANKR/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.012, - "maxLeverage": 50.0, - "info": { - "bracket": "1", - "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.012", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "65.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "690.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5690.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11940.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386940.0" - } - } - ], - "DUSK/USDT": [ + "ZRX/USDT": [ { "tier": 1.0, "currency": "USDT", "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, + "maxLeverage": 50.0, "info": { "bracket": "1", - "initialLeverage": "25", + "initialLeverage": "50", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.01", @@ -16682,225 +17706,13 @@ "tier": 6.0, "currency": "USDT", "minNotional": 1000000.0, - "maxNotional": 30000000.0, + "maxNotional": 5000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", - "maintMarginRatio": "0.5", - "cum": "386950.0" - } - } - ], - "BTCUSDT_220624": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 375000.0, - "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "375000", - "notionalFloor": "0", - "maintMarginRatio": "0.02", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 375000.0, - "maxNotional": 2000000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "2", - "initialLeverage": "10", - "notionalCap": "2000000", - "notionalFloor": "375000", - "maintMarginRatio": "0.05", - "cum": "11250.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 2000000.0, - "maxNotional": 4000000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "3", - "initialLeverage": "5", - "notionalCap": "4000000", - "notionalFloor": "2000000", - "maintMarginRatio": "0.1", - "cum": "111250.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 4000000.0, - "maxNotional": 10000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 4.0, - "info": { - "bracket": "4", - "initialLeverage": "4", - "notionalCap": "10000000", - "notionalFloor": "4000000", - "maintMarginRatio": "0.125", - "cum": "211250.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 10000000.0, - "maxNotional": 20000000.0, - "maintenanceMarginRate": 0.15, - "maxLeverage": 3.0, - "info": { - "bracket": "5", - "initialLeverage": "3", - "notionalCap": "20000000", - "notionalFloor": "10000000", - "maintMarginRatio": "0.15", - "cum": "461250.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 20000000.0, - "maxNotional": 40000000.0, - "maintenanceMarginRate": 0.25, - "maxLeverage": 2.0, - "info": { - "bracket": "6", - "initialLeverage": "2", - "notionalCap": "40000000", - "notionalFloor": "20000000", - "maintMarginRatio": "0.25", - "cum": "2461250.0" - } - }, - { - "tier": 7.0, - "currency": "USDT", - "minNotional": 40000000.0, - "maxNotional": 400000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "7", - "initialLeverage": "1", - "notionalCap": "400000000", - "notionalFloor": "40000000", - "maintMarginRatio": "0.5", - "cum": "1.246125E7" - } - } - ], - "CTSI/USDT": [ - { - "tier": 1.0, - "currency": "USDT", - "minNotional": 0.0, - "maxNotional": 5000.0, - "maintenanceMarginRate": 0.01, - "maxLeverage": 25.0, - "info": { - "bracket": "1", - "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", - "maintMarginRatio": "0.01", - "cum": "0.0" - } - }, - { - "tier": 2.0, - "currency": "USDT", - "minNotional": 5000.0, - "maxNotional": 25000.0, - "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, - "info": { - "bracket": "2", - "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", - "maintMarginRatio": "0.025", - "cum": "75.0" - } - }, - { - "tier": 3.0, - "currency": "USDT", - "minNotional": 25000.0, - "maxNotional": 100000.0, - "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, - "info": { - "bracket": "3", - "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", - "maintMarginRatio": "0.05", - "cum": "700.0" - } - }, - { - "tier": 4.0, - "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 250000.0, - "maintenanceMarginRate": 0.1, - "maxLeverage": 5.0, - "info": { - "bracket": "4", - "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", - "maintMarginRatio": "0.1", - "cum": "5700.0" - } - }, - { - "tier": 5.0, - "currency": "USDT", - "minNotional": 250000.0, - "maxNotional": 1000000.0, - "maintenanceMarginRate": 0.125, - "maxLeverage": 2.0, - "info": { - "bracket": "5", - "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", - "maintMarginRatio": "0.125", - "cum": "11950.0" - } - }, - { - "tier": 6.0, - "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 30000000.0, - "maintenanceMarginRate": 0.5, - "maxLeverage": 1.0, - "info": { - "bracket": "6", - "initialLeverage": "1", - "notionalCap": "30000000", + "notionalCap": "5000000", "notionalFloor": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" From 494e0529d2dcb70dba350ef5a8e5f7b57fa9396e Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 10 Jul 2022 19:31:14 +0200 Subject: [PATCH 074/220] Update conftest for leverage tiers --- tests/conftest.py | 62 ++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 2e447c281..0cf32545f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3166,60 +3166,46 @@ def leverage_tiers(): "AAVE/USDT": [ { 'min': 0, - 'max': 50000, + 'max': 5000, 'mmr': 0.01, 'lev': 50, 'maintAmt': 0.0 }, { - 'min': 50000, - 'max': 250000, + 'min': 5000, + 'max': 25000, 'mmr': 0.02, 'lev': 25, - 'maintAmt': 500.0 + 'maintAmt': 75.0 + }, + { + 'min': 25000, + 'max': 100000, + 'mmr': 0.05, + 'lev': 10, + 'maintAmt': 700.0 + }, + { + 'min': 100000, + 'max': 250000, + 'mmr': 0.1, + 'lev': 5, + 'maintAmt': 5700.0 }, { 'min': 250000, 'max': 1000000, - 'mmr': 0.05, - 'lev': 10, - 'maintAmt': 8000.0 - }, - { - 'min': 1000000, - 'max': 2000000, - 'mmr': 0.1, - 'lev': 5, - 'maintAmt': 58000.0 - }, - { - 'min': 2000000, - 'max': 5000000, 'mmr': 0.125, - 'lev': 4, - 'maintAmt': 108000.0 - }, - { - 'min': 5000000, - 'max': 10000000, - 'mmr': 0.1665, - 'lev': 3, - 'maintAmt': 315500.0 + 'lev': 2, + 'maintAmt': 11950.0 }, { 'min': 10000000, - 'max': 20000000, - 'mmr': 0.25, - 'lev': 2, - 'maintAmt': 1150500.0 + 'max': 50000000, + 'mmr': 0.5, + 'lev': 1, + 'maintAmt': 386950.0 }, - { - "min": 20000000, - "max": 50000000, - "mmr": 0.5, - "lev": 1, - "maintAmt": 6150500.0 - } ], "ADA/BUSD": [ { From 9086176f7385e16db201e98112e4c2548189c815 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 03:01:47 +0000 Subject: [PATCH 075/220] Bump pytest-mock from 3.8.1 to 3.8.2 Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.8.1 to 3.8.2. - [Release notes](https://github.com/pytest-dev/pytest-mock/releases) - [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.8.1...v3.8.2) --- updated-dependencies: - dependency-name: pytest-mock 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 50cb98fa1..6bd107809 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -12,7 +12,7 @@ pre-commit==2.19.0 pytest==7.1.2 pytest-asyncio==0.18.3 pytest-cov==3.0.0 -pytest-mock==3.8.1 +pytest-mock==3.8.2 pytest-random-order==1.0.4 isort==5.10.1 # For datetime mocking From 5070a04a82d57576c722f13030fcd270bdc50d89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 03:01:50 +0000 Subject: [PATCH 076/220] Bump mkdocs-material from 8.3.8 to 8.3.9 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.8 to 8.3.9. - [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/8.3.8...8.3.9) --- 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 fe00705b9..66e83a397 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,5 @@ mkdocs==1.3.0 -mkdocs-material==8.3.8 +mkdocs-material==8.3.9 mdx_truly_sane_lists==1.2 pymdown-extensions==9.5 jinja2==3.1.2 From b1d34dba9476b87f72869e48c9118bd7568409fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 03:02:12 +0000 Subject: [PATCH 077/220] Bump ccxt from 1.90.40 to 1.90.41 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.90.40 to 1.90.41. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.90.40...1.90.41) --- 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 2bce619d3..83f768e20 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.0 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.90.40 +ccxt==1.90.41 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.2 aiohttp==3.8.1 From c98786a4f6752719b5ff0a6483fa01b800a5319a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 03:02:17 +0000 Subject: [PATCH 078/220] Bump jsonschema from 4.6.1 to 4.6.2 Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.6.1 to 4.6.2. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.6.1...v4.6.2) --- updated-dependencies: - dependency-name: jsonschema 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 2bce619d3..2400f7699 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ arrow==1.2.2 cachetools==4.2.2 requests==2.28.1 urllib3==1.26.9 -jsonschema==4.6.1 +jsonschema==4.6.2 TA-Lib==0.4.24 technical==1.3.0 tabulate==0.8.10 From 719fa6f8e1b4600d08247bb9d8f385d924dc6038 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 03:02:39 +0000 Subject: [PATCH 079/220] Bump orjson from 3.7.6 to 3.7.7 Bumps [orjson](https://github.com/ijl/orjson) from 3.7.6 to 3.7.7. - [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.7.6...3.7.7) --- 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 2bce619d3..fa3a3ee6a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,7 +28,7 @@ py_find_1st==1.1.5 # Load ticker files 30% faster python-rapidjson==1.6 # Properly format api responses -orjson==3.7.6 +orjson==3.7.7 # Notify systemd sdnotify==0.3.2 From fa158ba8de02ff45c9cea5bd5c26ac40d8a1dcb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 05:14:41 +0000 Subject: [PATCH 080/220] Bump pre-commit from 2.19.0 to 2.20.0 Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.19.0 to 2.20.0. - [Release notes](https://github.com/pre-commit/pre-commit/releases) - [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) - [Commits](https://github.com/pre-commit/pre-commit/compare/v2.19.0...v2.20.0) --- updated-dependencies: - dependency-name: pre-commit 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 6bd107809..f2f77c2ba 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -8,7 +8,7 @@ coveralls==3.3.1 flake8==4.0.1 flake8-tidy-imports==4.8.0 mypy==0.961 -pre-commit==2.19.0 +pre-commit==2.20.0 pytest==7.1.2 pytest-asyncio==0.18.3 pytest-cov==3.0.0 From 7b998378ced8638b1f8436fd5593e5f20a0499d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 05:15:37 +0000 Subject: [PATCH 081/220] Bump numpy from 1.23.0 to 1.23.1 Bumps [numpy](https://github.com/numpy/numpy) from 1.23.0 to 1.23.1. - [Release notes](https://github.com/numpy/numpy/releases) - [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst) - [Commits](https://github.com/numpy/numpy/compare/v1.23.0...v1.23.1) --- updated-dependencies: - dependency-name: numpy 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 868f27cd7..9910efd3a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -numpy==1.23.0 +numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b From 7c6c2c4d6ed7adb1678d85e03ea8058ed6dd137a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 05:15:38 +0000 Subject: [PATCH 082/220] Bump cryptography from 37.0.2 to 37.0.4 Bumps [cryptography](https://github.com/pyca/cryptography) from 37.0.2 to 37.0.4. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/37.0.2...37.0.4) --- updated-dependencies: - dependency-name: cryptography 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 868f27cd7..cb3f577c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ pandas-ta==0.3.14b ccxt==1.90.41 # Pin cryptography for now due to rust build errors with piwheels -cryptography==37.0.2 +cryptography==37.0.4 aiohttp==3.8.1 SQLAlchemy==1.4.39 python-telegram-bot==13.13 From c06b524b4eac96ec57f136809d61347377ab2e2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 05:16:14 +0000 Subject: [PATCH 083/220] Bump urllib3 from 1.26.9 to 1.26.10 Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.9 to 1.26.10. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/1.26.10/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.9...1.26.10) --- updated-dependencies: - dependency-name: urllib3 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 868f27cd7..4db3e5866 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ python-telegram-bot==13.13 arrow==1.2.2 cachetools==4.2.2 requests==2.28.1 -urllib3==1.26.9 +urllib3==1.26.10 jsonschema==4.6.2 TA-Lib==0.4.24 technical==1.3.0 From 0bb8c8feba97476dc40bfc2f5cab801e1dcccd9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 05:23:01 +0000 Subject: [PATCH 084/220] Bump python-rapidjson from 1.6 to 1.8 Bumps [python-rapidjson](https://github.com/python-rapidjson/python-rapidjson) from 1.6 to 1.8. - [Release notes](https://github.com/python-rapidjson/python-rapidjson/releases) - [Changelog](https://github.com/python-rapidjson/python-rapidjson/blob/master/CHANGES.rst) - [Commits](https://github.com/python-rapidjson/python-rapidjson/compare/v1.6...v1.8) --- updated-dependencies: - dependency-name: python-rapidjson 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 459deadb6..1b730f2b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,7 +26,7 @@ joblib==1.1.0 py_find_1st==1.1.5 # Load ticker files 30% faster -python-rapidjson==1.6 +python-rapidjson==1.8 # Properly format api responses orjson==3.7.7 From 7d6b3d0e02158685a3c13c347aa897e325a371c9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 08:14:39 +0200 Subject: [PATCH 085/220] Update hyperopt param docs to be clear that non-conclusive parameters will be ignored --- docs/hyperopt.md | 3 ++- freqtrade/strategy/hyper.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index 63c7a4413..f44a68037 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -271,7 +271,8 @@ The last one we call `trigger` and use it to decide which buy trigger we want to !!! Note "Parameter space assignment" Parameters must either be assigned to a variable named `buy_*` or `sell_*` - or contain `space='buy'` | `space='sell'` to be assigned to a space correctly. - If no parameter is available for a space, you'll receive the error that no space was found when running hyperopt. + If no parameter is available for a space, you'll receive the error that no space was found when running hyperopt. + Parameters with unclear space (e.g. `adx_period = IntParameter(4, 24, default=14)` - no explicit nor implicit space) will not be detected and will therefore be ignored. So let's write the buy strategy using these values: diff --git a/freqtrade/strategy/hyper.py b/freqtrade/strategy/hyper.py index cdcfc969e..47377f238 100644 --- a/freqtrade/strategy/hyper.py +++ b/freqtrade/strategy/hyper.py @@ -191,6 +191,7 @@ def detect_parameters( and attr.category is not None and attr.category != category): raise OperationalException( f'Inconclusive parameter name {attr_name}, category: {attr.category}.') + if (category == attr.category or (attr_name.startswith(category + '_') and attr.category is None)): yield attr_name, attr From 523d8a84a810535588452d49c8f4489c3066ef66 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 10:22:51 +0200 Subject: [PATCH 086/220] skip "supports market order" for now until CCXT fixes their assignemnt bugs. --- freqtrade/exchange/common.py | 2 +- freqtrade/exchange/exchange.py | 11 +++++++---- tests/exchange/test_exchange.py | 6 +++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/freqtrade/exchange/common.py b/freqtrade/exchange/common.py index e5b6533c4..0046ba458 100644 --- a/freqtrade/exchange/common.py +++ b/freqtrade/exchange/common.py @@ -64,7 +64,6 @@ EXCHANGE_HAS_REQUIRED = [ 'fetchOrder', 'cancelOrder', 'createOrder', - # 'createLimitOrder', 'createMarketOrder', 'fetchBalance', # Public endpoints @@ -74,6 +73,7 @@ EXCHANGE_HAS_REQUIRED = [ EXCHANGE_HAS_OPTIONAL = [ # Private 'fetchMyTrades', # Trades for order - fee detection + # 'createLimitOrder', 'createMarketOrder', # Either OR for orders # 'setLeverage', # Margin/Futures trading # 'setMarginMode', # Margin/Futures trading # 'fetchFundingHistory', # Futures trading diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index cd13964c4..58d5ebb07 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -586,10 +586,13 @@ class Exchange: """ Checks if order-types configured in strategy/config are supported """ - if any(v == 'market' for k, v in order_types.items()): - if not self.exchange_has('createMarketOrder'): - raise OperationalException( - f'Exchange {self.name} does not support market orders.') + # TODO: Reenable once ccxt fixes createMarketOrder assignment - as well as + # Revert the change in test_validate_ordertypes. + + # if any(v == 'market' for k, v in order_types.items()): + # if not self.exchange_has('createMarketOrder'): + # raise OperationalException( + # f'Exchange {self.name} does not support market orders.') if (order_types.get("stoploss_on_exchange") and not self._ft_has.get("stoploss_on_exchange", False)): diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index acd48b3fd..69969e527 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1027,9 +1027,9 @@ def test_validate_ordertypes(default_conf, mocker): 'stoploss': 'market', 'stoploss_on_exchange': False } - with pytest.raises(OperationalException, - match=r'Exchange .* does not support market orders.'): - Exchange(default_conf) + # with pytest.raises(OperationalException, + # match=r'Exchange .* does not support market orders.'): + # Exchange(default_conf) default_conf['order_types'] = { 'entry': 'limit', From f8e35d876018e1a80918827f40d142a3a103f6f4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 10:30:05 +0200 Subject: [PATCH 087/220] Add TODO to disabled test --- tests/exchange/test_exchange.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 69969e527..f09d647ce 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1027,6 +1027,7 @@ def test_validate_ordertypes(default_conf, mocker): 'stoploss': 'market', 'stoploss_on_exchange': False } + # TODO: Revert once createMarketOrder is available again. # with pytest.raises(OperationalException, # match=r'Exchange .* does not support market orders.'): # Exchange(default_conf) From 6ac1aa15f582d8665936c0658c09f0ba308f68d0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 10:36:19 +0200 Subject: [PATCH 088/220] Reenable ccxt order checks --- freqtrade/exchange/exchange.py | 11 ++++------- tests/exchange/test_exchange.py | 7 +++---- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 58d5ebb07..cd13964c4 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -586,13 +586,10 @@ class Exchange: """ Checks if order-types configured in strategy/config are supported """ - # TODO: Reenable once ccxt fixes createMarketOrder assignment - as well as - # Revert the change in test_validate_ordertypes. - - # if any(v == 'market' for k, v in order_types.items()): - # if not self.exchange_has('createMarketOrder'): - # raise OperationalException( - # f'Exchange {self.name} does not support market orders.') + if any(v == 'market' for k, v in order_types.items()): + if not self.exchange_has('createMarketOrder'): + raise OperationalException( + f'Exchange {self.name} does not support market orders.') if (order_types.get("stoploss_on_exchange") and not self._ft_has.get("stoploss_on_exchange", False)): diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index f09d647ce..acd48b3fd 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1027,10 +1027,9 @@ def test_validate_ordertypes(default_conf, mocker): 'stoploss': 'market', 'stoploss_on_exchange': False } - # TODO: Revert once createMarketOrder is available again. - # with pytest.raises(OperationalException, - # match=r'Exchange .* does not support market orders.'): - # Exchange(default_conf) + with pytest.raises(OperationalException, + match=r'Exchange .* does not support market orders.'): + Exchange(default_conf) default_conf['order_types'] = { 'entry': 'limit', From 64f89af69e8e88f4c24bf0a8dace2b740821287b Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 10:43:21 +0200 Subject: [PATCH 089/220] Add Explicit test for "has" checks --- tests/exchange/test_ccxt_compat.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 50154bcaf..74106f28b 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -153,6 +153,25 @@ class TestCCXTExchange(): assert isinstance(markets[pair], dict) assert exchange.market_is_spot(markets[pair]) + def test_has_validations(self, exchange): + + exchange, exchangename = exchange + + exchange.validate_ordertypes({ + 'entry': 'limit', + 'exit': 'limit', + 'stoploss': 'limit', + }) + + if exchangename == 'gateio': + # gateio doesn't have market orders on spot + return + exchange.validate_ordertypes({ + 'entry': 'market', + 'exit': 'market', + 'stoploss': 'market', + }) + def test_load_markets_futures(self, exchange_futures): exchange, exchangename = exchange_futures if not exchange: From ec3179156c200da0649c1604ce7a1e29561d09d9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 11:48:24 +0200 Subject: [PATCH 090/220] Revert unwanted changes. --- .gitignore | 5 -- freqtrade/templates/sample_strategy.py | 27 ++++++-- .../templates/strategy_analysis_example.ipynb | 61 +++---------------- 3 files changed, 33 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index 5042dfb9b..97f77f779 100644 --- a/.gitignore +++ b/.gitignore @@ -105,8 +105,3 @@ target/ !config_examples/config_ftx.example.json !config_examples/config_full.example.json !config_examples/config_kraken.example.json -doc/doc-filelist.js -.gitignore -.gitignore -doc/doc-style.css -doc/doc-script.js diff --git a/freqtrade/templates/sample_strategy.py b/freqtrade/templates/sample_strategy.py index 1b49f82c9..1b375714a 100644 --- a/freqtrade/templates/sample_strategy.py +++ b/freqtrade/templates/sample_strategy.py @@ -178,10 +178,29 @@ class SampleStrategy(IStrategy): # RSI dataframe['rsi'] = ta.RSI(dataframe) - # Stochastic RSI - stoch_rsi = ta.STOCHRSI(dataframe) - dataframe['fastd_rsi'] = stoch_rsi['fastd'] - dataframe['fastk_rsi'] = stoch_rsi['fastk'] + # # Inverse Fisher transform on RSI: values [-1.0, 1.0] (https://goo.gl/2JGGoy) + # rsi = 0.1 * (dataframe['rsi'] - 50) + # dataframe['fisher_rsi'] = (np.exp(2 * rsi) - 1) / (np.exp(2 * rsi) + 1) + + # # Inverse Fisher transform on RSI normalized: values [0.0, 100.0] (https://goo.gl/2JGGoy) + # dataframe['fisher_rsi_norma'] = 50 * (dataframe['fisher_rsi'] + 1) + + # # Stochastic Slow + # stoch = ta.STOCH(dataframe) + # dataframe['slowd'] = stoch['slowd'] + # dataframe['slowk'] = stoch['slowk'] + + # Stochastic Fast + stoch_fast = ta.STOCHF(dataframe) + dataframe['fastd'] = stoch_fast['fastd'] + dataframe['fastk'] = stoch_fast['fastk'] + + # # Stochastic RSI + # Please read https://github.com/freqtrade/freqtrade/issues/2961 before using this. + # STOCHRSI is NOT aligned with tradingview, which may result in non-expected results. + # stoch_rsi = ta.STOCHRSI(dataframe) + # dataframe['fastd_rsi'] = stoch_rsi['fastd'] + # dataframe['fastk_rsi'] = stoch_rsi['fastk'] # MACD macd = ta.MACD(dataframe) diff --git a/freqtrade/templates/strategy_analysis_example.ipynb b/freqtrade/templates/strategy_analysis_example.ipynb index 33182dbf0..93e4b83ae 100644 --- a/freqtrade/templates/strategy_analysis_example.ipynb +++ b/freqtrade/templates/strategy_analysis_example.ipynb @@ -19,27 +19,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "OperationalException", - "evalue": "Directory `/Users/surfer/Software/MMM/develop/freqtrade/freqtrade/templates/user_data` does not exist. Please use `freqtrade create-userdir` to create a user directory", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mOperationalException\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [2]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfreqtrade\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mconfiguration\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Configuration\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# Customize these according to your needs.\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m# Initialize empty configuration object\u001b[39;00m\n\u001b[0;32m----> 7\u001b[0m config \u001b[38;5;241m=\u001b[39m \u001b[43mConfiguration\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_files\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;66;03m# Optionally, use existing configuration file\u001b[39;00m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;66;03m# config = Configuration.from_files([\"config.json\"])\u001b[39;00m\n\u001b[1;32m 10\u001b[0m \n\u001b[1;32m 11\u001b[0m \u001b[38;5;66;03m# Define some constants\u001b[39;00m\n\u001b[1;32m 12\u001b[0m config[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtimeframe\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1m\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", - "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:60\u001b[0m, in \u001b[0;36mConfiguration.from_files\u001b[0;34m(files)\u001b[0m\n\u001b[1;32m 58\u001b[0m \u001b[38;5;66;03m# Keep this method as staticmethod, so it can be used from interactive environments\u001b[39;00m\n\u001b[1;32m 59\u001b[0m c \u001b[38;5;241m=\u001b[39m Configuration({\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mconfig\u001b[39m\u001b[38;5;124m'\u001b[39m: files}, RunMode\u001b[38;5;241m.\u001b[39mOTHER)\n\u001b[0;32m---> 60\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:42\u001b[0m, in \u001b[0;36mConfiguration.get_config\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;124;03mReturn the config. Use this method to get the bot config\u001b[39;00m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;124;03m:return: Dict: Bot config\u001b[39;00m\n\u001b[1;32m 40\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconfig \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m---> 42\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconfig \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 44\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconfig\n", - "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:92\u001b[0m, in \u001b[0;36mConfiguration.load_config\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 88\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_common_options(config)\n\u001b[1;32m 90\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_trading_options(config)\n\u001b[0;32m---> 92\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_process_optimize_options\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 94\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_plot_options(config)\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_data_options(config)\n", - "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:249\u001b[0m, in \u001b[0;36mConfiguration._process_optimize_options\u001b[0;34m(self, config)\u001b[0m\n\u001b[1;32m 242\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_args_to_config(config, argname\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mfee\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 243\u001b[0m logstring\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mParameter --fee detected, \u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 244\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124msetting fee to: \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m ...\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 246\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_args_to_config(config, argname\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtimerange\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 247\u001b[0m logstring\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mParameter --timerange detected: \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m ...\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m--> 249\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_process_datadir_options\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 251\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_args_to_config(config, argname\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mstrategy_list\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 252\u001b[0m logstring\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mUsing strategy list of \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m strategies\u001b[39m\u001b[38;5;124m'\u001b[39m, logfun\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mlen\u001b[39m)\n\u001b[1;32m 254\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_args_to_config(\n\u001b[1;32m 255\u001b[0m config,\n\u001b[1;32m 256\u001b[0m argname\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mrecursive_strategy_search\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 257\u001b[0m logstring\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mRecursively searching for a strategy in the strategies folder.\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 258\u001b[0m )\n", - "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/configuration.py:180\u001b[0m, in \u001b[0;36mConfiguration._process_datadir_options\u001b[0;34m(self, config)\u001b[0m\n\u001b[1;32m 177\u001b[0m config\u001b[38;5;241m.\u001b[39mupdate({\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser_data_dir\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;28mstr\u001b[39m(Path\u001b[38;5;241m.\u001b[39mcwd() \u001b[38;5;241m/\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser_data\u001b[39m\u001b[38;5;124m'\u001b[39m)})\n\u001b[1;32m 179\u001b[0m \u001b[38;5;66;03m# reset to user_data_dir so this contains the absolute path.\u001b[39;00m\n\u001b[0;32m--> 180\u001b[0m config[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser_data_dir\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[43mcreate_userdata_dir\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43muser_data_dir\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcreate_dir\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m 181\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mUsing user-data directory: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m ...\u001b[39m\u001b[38;5;124m'\u001b[39m, config[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser_data_dir\u001b[39m\u001b[38;5;124m'\u001b[39m])\n\u001b[1;32m 183\u001b[0m config\u001b[38;5;241m.\u001b[39mupdate({\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdatadir\u001b[39m\u001b[38;5;124m'\u001b[39m: create_datadir(config, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39margs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdatadir\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m))})\n", - "File \u001b[0;32m~/Software/MMM/develop/freqtrade/freqtrade/configuration/directory_operations.py:61\u001b[0m, in \u001b[0;36mcreate_userdata_dir\u001b[0;34m(directory, create_dir)\u001b[0m\n\u001b[1;32m 59\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mCreated user-data directory: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfolder\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OperationalException(\n\u001b[1;32m 62\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mDirectory `\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfolder\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m` does not exist. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 63\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPlease use `freqtrade create-userdir` to create a user directory\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 65\u001b[0m \u001b[38;5;66;03m# Create required subdirectories\u001b[39;00m\n\u001b[1;32m 66\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m f \u001b[38;5;129;01min\u001b[39;00m sub_dirs:\n", - "\u001b[0;31mOperationalException\u001b[0m: Directory `/Users/surfer/Software/MMM/develop/freqtrade/freqtrade/templates/user_data` does not exist. Please use `freqtrade create-userdir` to create a user directory" - ] - } - ], + "outputs": [], "source": [ "from pathlib import Path\n", "from freqtrade.configuration import Configuration\n", @@ -52,9 +34,9 @@ "# config = Configuration.from_files([\"config.json\"])\n", "\n", "# Define some constants\n", - "config[\"timeframe\"] = \"1m\"\n", + "config[\"timeframe\"] = \"5m\"\n", "# Name of the strategy class\n", - "config[\"strategy\"] = \"MMMOracle\"\n", + "config[\"strategy\"] = \"SampleStrategy\"\n", "# Location of the data\n", "data_location = Path(config['user_data_dir'], 'data', 'binance')\n", "# Pair to analyze - Only use one pair here\n", @@ -154,21 +136,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'config' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [3]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfreqtrade\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdata\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mbtanalysis\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m load_backtest_data, load_backtest_stats\n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# if backtest_dir points to a directory, it'll automatically load the last backtest file.\u001b[39;00m\n\u001b[0;32m----> 4\u001b[0m backtest_dir \u001b[38;5;241m=\u001b[39m \u001b[43mconfig\u001b[49m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124muser_data_dir\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m/\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbacktest_results\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", - "\u001b[0;31mNameError\u001b[0m: name 'config' is not defined" - ] - } - ], + "outputs": [], "source": [ "from freqtrade.data.btanalysis import load_backtest_data, load_backtest_stats\n", "\n", @@ -277,20 +247,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Series([], Name: exit_reason, dtype: int64)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "from freqtrade.data.btanalysis import load_trades_from_db\n", "\n", @@ -404,7 +363,7 @@ "metadata": { "file_extension": ".py", "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -418,7 +377,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.7" + "version": "3.8.5" }, "mimetype": "text/x-python", "name": "python", From 8e8f026ea77a11259e93e1691a737b0c079f7f83 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 12:10:29 +0200 Subject: [PATCH 091/220] Telegram candle message should be configurable --- config_examples/config_full.example.json | 3 ++- docs/telegram-usage.md | 5 +++-- freqtrade/constants.py | 4 ++++ freqtrade/freqtradebot.py | 4 ++-- freqtrade/rpc/telegram.py | 23 +++++++++++++++-------- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/config_examples/config_full.example.json b/config_examples/config_full.example.json index 6382e1baf..e2e9a16fd 100644 --- a/config_examples/config_full.example.json +++ b/config_examples/config_full.example.json @@ -155,7 +155,8 @@ "entry_cancel": "on", "exit_cancel": "on", "protection_trigger": "off", - "protection_trigger_global": "on" + "protection_trigger_global": "on", + "show_candle": "off" }, "reload": true, "balance_dust_level": 0.01 diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index 2145797b4..9853e15c6 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -97,7 +97,8 @@ Example configuration showing the different settings: "entry_fill": "off", "exit_fill": "off", "protection_trigger": "off", - "protection_trigger_global": "on" + "protection_trigger_global": "on", + "show_candle": "off" }, "reload": true, "balance_dust_level": 0.01 @@ -108,7 +109,7 @@ Example configuration showing the different settings: `exit` notifications are sent when the order is placed, while `exit_fill` notifications are sent when the order is filled on the exchange. `*_fill` notifications are off by default and must be explicitly enabled. `protection_trigger` notifications are sent when a protection triggers and `protection_trigger_global` notifications trigger when global protections are triggered. - +`show_candle` - show candle values as part of entry/exit messages. Only possible value is "ohlc". `balance_dust_level` will define what the `/balance` command takes as "dust" - Currencies with a balance below this will be shown. `reload` allows you to disable reload-buttons on selected messages. diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 18dbea259..ce7c0ff83 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -313,6 +313,10 @@ CONF_SCHEMA = { 'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS, }, + 'show_candle': { + 'type': 'string', + 'enum': ['off', 'ohlc'], + }, } }, 'reload': {'type': 'boolean'}, diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 2d16dc9ff..fe8bcc89b 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -868,7 +868,7 @@ class FreqtradeBot(LoggingMixin): if analyzed_candle is not None: candle_columns = analyzed_candle[['date', 'open', 'high', 'low', 'close']] msg.update({ - 'analyzed_candle': candle_columns.to_json(date_unit='s', date_format='iso') + 'analyzed_candle': candle_columns.to_dict() }) # Send the message @@ -1567,7 +1567,7 @@ class FreqtradeBot(LoggingMixin): if analyzed_candle is not None: candle_columns = analyzed_candle[['date', 'open', 'high', 'low', 'close']] msg.update({ - 'analyzed_candle': candle_columns.to_json(date_unit='s', date_format='iso') + 'analyzed_candle': candle_columns.to_dict() }) # Send the message diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 16a851ce1..9ade8cb5f 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -243,6 +243,19 @@ class Telegram(RPCHandler): """ return f"{msg['exchange']}{' (dry)' if self._config['dry_run'] else ''}" + def _add_analyzed_candle(self, msg) -> str: + candle_val = self._config['telegram'].get( + 'notification_settings', {}).get('show_candle', 'off') + if candle_val != 'off' and msg.get('analyzed_candle'): + if candle_val == 'ohlc': + candle_json = msg['analyzed_candle'] + return ( + f"*Candle OHLC*: `{candle_json['open']}, {candle_json['high']}, " + f"{candle_json['low']}, {candle_json['close']}`\n" + ) + + return '' + def _format_entry_msg(self, msg: Dict[str, Any]) -> str: if self._rpc._fiat_converter: msg['stake_amount_fiat'] = self._rpc._fiat_converter.convert_amount( @@ -259,8 +272,7 @@ class Telegram(RPCHandler): f" {entry_side['entered'] if is_fill else entry_side['enter']} {msg['pair']}" f" (#{msg['trade_id']})\n" ) - if msg.get('analyzed_candle'): - message += f"*Analyzed Candle:* `{msg['analyzed_candle']}`\n" + message += self._add_analyzed_candle(msg) message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else "" message += f"*Amount:* `{msg['amount']:.8f}`\n" if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0: @@ -308,12 +320,7 @@ class Telegram(RPCHandler): message = ( f"{msg['emoji']} *{self._exchange_from_msg(msg)}:* " f"{'Exited' if is_fill else 'Exiting'} {msg['pair']} (#{msg['trade_id']})\n" - ) - if not is_fill and msg.get('analyzed_candle'): - message += ( - f"*Analyzed Candle:* `{msg['analyzed_candle']}`\n" - ) - message += ( + f"{self._add_analyzed_candle(msg)}" f"*{'Profit' if is_fill else 'Unrealized Profit'}:* " f"`{msg['profit_ratio']:.2%}{msg['profit_extra']}`\n" f"*Enter Tag:* `{msg['enter_tag']}`\n" From 9a3a2f9013003182b9b5fe014e9d6679138e9f2b Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 13:55:32 +0200 Subject: [PATCH 092/220] Simplify adding candle to message --- freqtrade/freqtradebot.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index fe8bcc89b..bde9ea8aa 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -861,8 +861,15 @@ class FreqtradeBot(LoggingMixin): 'current_rate': current_rate, } + self._analyzed_candle_to_msg(trade.pair, msg) + + # Send the message + self.rpc.send_msg(msg) + + def _analyzed_candle_to_msg(self, pair: str, msg: Dict): + """Msg dict will be enhanced with analyzed_candle if possible.""" # display the candle analyzed in telegram - analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(trade.pair, + analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(pair, self.strategy.timeframe) analyzed_candle = analyzed_df.iloc[-1] if len(analyzed_df) > 0 else None if analyzed_candle is not None: @@ -871,9 +878,6 @@ class FreqtradeBot(LoggingMixin): 'analyzed_candle': candle_columns.to_dict() }) - # Send the message - self.rpc.send_msg(msg) - def _notify_enter_cancel(self, trade: Trade, order_type: str, reason: str) -> None: """ Sends rpc notification when a entry order cancel occurred. @@ -1560,15 +1564,7 @@ class FreqtradeBot(LoggingMixin): 'fiat_currency': self.config['fiat_display_currency'], }) - # display the candle analyzed in telegram - analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(trade.pair, - self.strategy.timeframe) - analyzed_candle = analyzed_df.iloc[-1] if len(analyzed_df) > 0 else None - if analyzed_candle is not None: - candle_columns = analyzed_candle[['date', 'open', 'high', 'low', 'close']] - msg.update({ - 'analyzed_candle': candle_columns.to_dict() - }) + self._analyzed_candle_to_msg(trade.pair, msg) # Send the message self.rpc.send_msg(msg) From f9d3775d4c36f1c45a137f5919ebef12f6703c1e Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 14:09:39 +0200 Subject: [PATCH 093/220] Move "candle" logic for message to telegram this avoids calling this method unless necessary --- freqtrade/freqtradebot.py | 16 ---------------- freqtrade/rpc/telegram.py | 21 ++++++++++++--------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index bde9ea8aa..469bfda7e 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -861,23 +861,9 @@ class FreqtradeBot(LoggingMixin): 'current_rate': current_rate, } - self._analyzed_candle_to_msg(trade.pair, msg) - # Send the message self.rpc.send_msg(msg) - def _analyzed_candle_to_msg(self, pair: str, msg: Dict): - """Msg dict will be enhanced with analyzed_candle if possible.""" - # display the candle analyzed in telegram - analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(pair, - self.strategy.timeframe) - analyzed_candle = analyzed_df.iloc[-1] if len(analyzed_df) > 0 else None - if analyzed_candle is not None: - candle_columns = analyzed_candle[['date', 'open', 'high', 'low', 'close']] - msg.update({ - 'analyzed_candle': candle_columns.to_dict() - }) - def _notify_enter_cancel(self, trade: Trade, order_type: str, reason: str) -> None: """ Sends rpc notification when a entry order cancel occurred. @@ -1564,8 +1550,6 @@ class FreqtradeBot(LoggingMixin): 'fiat_currency': self.config['fiat_display_currency'], }) - self._analyzed_candle_to_msg(trade.pair, msg) - # Send the message self.rpc.send_msg(msg) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 9ade8cb5f..2aff1d210 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -243,16 +243,19 @@ class Telegram(RPCHandler): """ return f"{msg['exchange']}{' (dry)' if self._config['dry_run'] else ''}" - def _add_analyzed_candle(self, msg) -> str: + def _add_analyzed_candle(self, pair: str) -> str: candle_val = self._config['telegram'].get( 'notification_settings', {}).get('show_candle', 'off') - if candle_val != 'off' and msg.get('analyzed_candle'): + if candle_val != 'off': if candle_val == 'ohlc': - candle_json = msg['analyzed_candle'] - return ( - f"*Candle OHLC*: `{candle_json['open']}, {candle_json['high']}, " - f"{candle_json['low']}, {candle_json['close']}`\n" - ) + analyzed_df, _ = self._rpc._freqtrade.dataprovider.get_analyzed_dataframe( + pair, self._config['timeframe']) + candle = analyzed_df.iloc[-1].squeeze() if len(analyzed_df) > 0 else None + if candle is not None: + return ( + f"*Candle OHLC*: `{candle['open']}, {candle['high']}, " + f"{candle['low']}, {candle['close']}`\n" + ) return '' @@ -272,7 +275,7 @@ class Telegram(RPCHandler): f" {entry_side['entered'] if is_fill else entry_side['enter']} {msg['pair']}" f" (#{msg['trade_id']})\n" ) - message += self._add_analyzed_candle(msg) + message += self._add_analyzed_candle(msg['pair']) message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else "" message += f"*Amount:* `{msg['amount']:.8f}`\n" if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0: @@ -320,7 +323,7 @@ class Telegram(RPCHandler): message = ( f"{msg['emoji']} *{self._exchange_from_msg(msg)}:* " f"{'Exited' if is_fill else 'Exiting'} {msg['pair']} (#{msg['trade_id']})\n" - f"{self._add_analyzed_candle(msg)}" + f"{self._add_analyzed_candle(msg['pair'])}" f"*{'Profit' if is_fill else 'Unrealized Profit'}:* " f"`{msg['profit_ratio']:.2%}{msg['profit_extra']}`\n" f"*Enter Tag:* `{msg['enter_tag']}`\n" From bf992fd9dfce74e916a961164436a8349df25aa1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 14:09:44 +0200 Subject: [PATCH 094/220] Add test for newly added functionality --- tests/rpc/test_rpc_telegram.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index e36d98083..91ee92fd7 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -12,6 +12,7 @@ from unittest.mock import ANY, MagicMock import arrow import pytest +from pandas import DataFrame from telegram import Chat, Message, ReplyKeyboardMarkup, Update from telegram.error import BadRequest, NetworkError, TelegramError @@ -1655,8 +1656,17 @@ def test_show_config_handle(default_conf, update, mocker) -> None: (RPCMessageType.ENTRY, 'Long', 'long_signal_01', 1.0), (RPCMessageType.ENTRY, 'Long', 'long_signal_01', 5.0), (RPCMessageType.ENTRY, 'Short', 'short_signal_01', 2.0)]) -def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type, - enter, enter_signal, leverage) -> None: +def test_send_msg_enter_notification(default_conf, mocker, caplog, message_type, + enter, enter_signal, leverage) -> None: + default_conf['telegram']['notification_settings']['show_candle'] = 'ohlc' + df = DataFrame({ + 'open': [1.1], + 'high': [2.2], + 'low': [1.0], + 'close': [1.5], + }) + mocker.patch('freqtrade.data.dataprovider.DataProvider.get_analyzed_dataframe', + return_value=(df, 1)) msg = { 'type': message_type, @@ -1674,6 +1684,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type, 'fiat_currency': 'USD', 'current_rate': 1.099e-05, 'amount': 1333.3333333333335, + 'analyzed_candle': {'open': 1.1, 'high': 2.2, 'low': 1.0, 'close': 1.5}, 'open_date': arrow.utcnow().shift(hours=-1) } telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) @@ -1683,6 +1694,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type, assert msg_mock.call_args[0][0] == ( f'\N{LARGE BLUE CIRCLE} *Binance (dry):* {enter} ETH/BTC (#1)\n' + '*Candle OHLC*: `1.1, 2.2, 1.0, 1.5`\n' f'*Enter Tag:* `{enter_signal}`\n' '*Amount:* `1333.33333333`\n' f'{leverage_text}' @@ -1710,7 +1722,8 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type, @pytest.mark.parametrize('message_type,enter_signal', [ (RPCMessageType.ENTRY_CANCEL, 'long_signal_01'), (RPCMessageType.ENTRY_CANCEL, 'short_signal_01')]) -def test_send_msg_buy_cancel_notification(default_conf, mocker, message_type, enter_signal) -> None: +def test_send_msg_enter_cancel_notification( + default_conf, mocker, message_type, enter_signal) -> None: telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) From b9ba94d644c4408059093e0cb0ada7fee1a4ac46 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 16:07:58 +0200 Subject: [PATCH 095/220] Bump ccxt to 1.90.47 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 115ae734e..2bb3b4b75 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.90.41 +ccxt==1.90.47 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.4 aiohttp==3.8.1 From 5c164efdb6845313eee57d849aff04f3b93eb93d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Jul 2022 16:09:12 +0200 Subject: [PATCH 096/220] Also check for createLimitOrder as optionals --- freqtrade/exchange/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/exchange/common.py b/freqtrade/exchange/common.py index 0046ba458..5765dc459 100644 --- a/freqtrade/exchange/common.py +++ b/freqtrade/exchange/common.py @@ -73,7 +73,7 @@ EXCHANGE_HAS_REQUIRED = [ EXCHANGE_HAS_OPTIONAL = [ # Private 'fetchMyTrades', # Trades for order - fee detection - # 'createLimitOrder', 'createMarketOrder', # Either OR for orders + 'createLimitOrder', 'createMarketOrder', # Either OR for orders # 'setLeverage', # Margin/Futures trading # 'setMarginMode', # Margin/Futures trading # 'fetchFundingHistory', # Futures trading From cdc58058d72aca1bf11cfd108f01f79226056277 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 14 Jul 2022 19:40:26 +0200 Subject: [PATCH 097/220] Add candletype to notebook example closes #7084, closes #7073 --- docs/strategy_analysis_example.md | 4 +++- freqtrade/templates/strategy_analysis_example.ipynb | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/strategy_analysis_example.md b/docs/strategy_analysis_example.md index ae0c6a6a3..fbfce37d1 100644 --- a/docs/strategy_analysis_example.md +++ b/docs/strategy_analysis_example.md @@ -31,11 +31,13 @@ pair = "BTC/USDT" ```python # Load data using values set above from freqtrade.data.history import load_pair_history +from freqtrade.enums import CandleType candles = load_pair_history(datadir=data_location, timeframe=config["timeframe"], pair=pair, data_format = "hdf5", + candle_type=CandleType.SPOT, ) # Confirm success @@ -93,7 +95,7 @@ from freqtrade.data.btanalysis import load_backtest_data, load_backtest_stats # if backtest_dir points to a directory, it'll automatically load the last backtest file. backtest_dir = config["user_data_dir"] / "backtest_results" -# backtest_dir can also point to a specific file +# backtest_dir can also point to a specific file # backtest_dir = config["user_data_dir"] / "backtest_results/backtest-result-2020-07-01_20-04-22.json" ``` diff --git a/freqtrade/templates/strategy_analysis_example.ipynb b/freqtrade/templates/strategy_analysis_example.ipynb index 93e4b83ae..a7430c225 100644 --- a/freqtrade/templates/strategy_analysis_example.ipynb +++ b/freqtrade/templates/strategy_analysis_example.ipynb @@ -51,11 +51,13 @@ "source": [ "# Load data using values set above\n", "from freqtrade.data.history import load_pair_history\n", + "from freqtrade.enums import CandleType\n", "\n", "candles = load_pair_history(datadir=data_location,\n", " timeframe=config[\"timeframe\"],\n", " pair=pair,\n", " data_format = \"hdf5\",\n", + " candle_type=CandleType.SPOT,\n", " )\n", "\n", "# Confirm success\n", From b657a4df2375aeebc9ad4f1e4c4eff995f7fd90a Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 15 Jul 2022 18:55:30 +0200 Subject: [PATCH 098/220] Improve hyperopt docs part of #7088 --- docs/hyperopt.md | 24 ++++++++++++++++++++++-- docs/strategy-advanced.md | 2 ++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index f44a68037..55fe8f008 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -335,6 +335,7 @@ There are four parameter types each suited for different purposes. ## Optimizing an indicator parameter Assuming you have a simple strategy in mind - a EMA cross strategy (2 Moving averages crossing) - and you'd like to find the ideal parameters for this strategy. +By default, we assume a stoploss of 5% - and a take-profit (`minimal_roi`) of 10% - which means freqtrade will sell the trade once 10% profit has been reached. ``` python from pandas import DataFrame @@ -349,6 +350,9 @@ import freqtrade.vendor.qtpylib.indicators as qtpylib class MyAwesomeStrategy(IStrategy): stoploss = -0.05 timeframe = '15m' + minimal_roi = { + "0": 0.10 + }, # Define the parameter spaces buy_ema_short = IntParameter(3, 50, default=5) buy_ema_long = IntParameter(15, 200, default=50) @@ -383,7 +387,7 @@ class MyAwesomeStrategy(IStrategy): return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - conditions = [] + conditions = [] conditions.append(qtpylib.crossed_above( dataframe[f'ema_long_{self.buy_ema_long.value}'], dataframe[f'ema_short_{self.buy_ema_short.value}'] )) @@ -404,7 +408,7 @@ Using `self.buy_ema_short.range` will return a range object containing all entri In this case (`IntParameter(3, 50, default=5)`), the loop would run for all numbers between 3 and 50 (`[3, 4, 5, ... 49, 50]`). By using this in a loop, hyperopt will generate 48 new columns (`['buy_ema_3', 'buy_ema_4', ... , 'buy_ema_50']`). -Hyperopt itself will then use the selected value to create the buy and sell signals +Hyperopt itself will then use the selected value to create the buy and sell signals. While this strategy is most likely too simple to provide consistent profit, it should serve as an example how optimize indicator parameters. @@ -868,6 +872,22 @@ To combat these, you have multiple options: * reduce the number of parallel processes (`-j `) * Increase the memory of your machine +## The objective has been evaluated at this point before. + +If you see `The objective has been evaluated at this point before.` - then this is a sign that your space has been exhausted, or is close to that. +Basically all points in your space have been hit (or a local minima has been hit) - and hyperopt does no longer find points in the multi-dimensional space it did not try yet. +Freqtrade tries to counter the "local minima" problem by using new, randomized points in this case. + +Example: + +``` python +buy_ema_short = IntParameter(5, 20, default=10, space="buy", optimize=True) +# This is the only parameter in the buy space +``` + +The `buy_ema_short` space has 15 possible values (`5, 6, ... 19, 20`). If you now run hyperopt for the buy space, hyperopt will only have 15 values to try before running out of options. +Your epochs should therefore be aligned to the possible values - or you should be ready to interrupt a run if you norice a lot of `The objective has been evaluated at this point before.` warnings. + ## Show details of Hyperopt results After you run Hyperopt for the desired amount of epochs, you can later list all results for analysis, select only best or profitable once, and show the details for any of the epochs previously evaluated. This can be done with the `hyperopt-list` and `hyperopt-show` sub-commands. The usage of these sub-commands is described in the [Utils](utils.md#list-hyperopt-results) chapter. diff --git a/docs/strategy-advanced.md b/docs/strategy-advanced.md index 374c675a2..a3115bfb2 100644 --- a/docs/strategy-advanced.md +++ b/docs/strategy-advanced.md @@ -224,3 +224,5 @@ for val in self.buy_ema_short.range: # Append columns to existing dataframe merged_frame = pd.concat(frames, axis=1) ``` + +Freqtrade does however also counter this by running `dataframe.copy()` on the dataframe right after the `populate_indicators()` method - so performance implications of this should be low to non-existant. From fada432f49611da259b720c58e0dfd8259936276 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 15 Jul 2022 19:48:12 +0200 Subject: [PATCH 099/220] Pin markdown docs dependency --- docs/requirements-docs.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 66e83a397..22d92c65d 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,3 +1,4 @@ +markdown==3.3.7 mkdocs==1.3.0 mkdocs-material==8.3.9 mdx_truly_sane_lists==1.2 From 1c7f60103db564fb5abf0ac0db83600e713c4586 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 15 Jul 2022 20:26:24 +0200 Subject: [PATCH 100/220] Don't use master for publish CI action --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4fe1ad853..7b077be04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -351,7 +351,7 @@ jobs: python setup.py sdist bdist_wheel - name: Publish to PyPI (Test) - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@v1.5.0 if: (github.event_name == 'release') with: user: __token__ @@ -359,7 +359,7 @@ jobs: repository_url: https://test.pypi.org/legacy/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@v1.5.0 if: (github.event_name == 'release') with: user: __token__ From 29efe75a6fc307a7224017765134199bed7dc11e Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 11:15:14 +0200 Subject: [PATCH 101/220] Update hyperoptable strategy to use V3 interface --- tests/rpc/test_rpc_apiserver.py | 1 + .../strategy/strats/hyperoptable_strategy.py | 4 +- .../strats/hyperoptable_strategy_v2.py | 54 +++++++++++++++++++ tests/strategy/test_interface.py | 2 +- tests/strategy/test_strategy_loading.py | 6 +-- 5 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 tests/strategy/strats/hyperoptable_strategy_v2.py diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index c0de54c6d..57c08f48e 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1398,6 +1398,7 @@ def test_api_strategies(botclient): assert rc.json() == {'strategies': [ 'HyperoptableStrategy', + 'HyperoptableStrategyV2', 'InformativeDecoratorTest', 'StrategyTestV2', 'StrategyTestV3', diff --git a/tests/strategy/strats/hyperoptable_strategy.py b/tests/strategy/strats/hyperoptable_strategy.py index 876b31b14..9850a5675 100644 --- a/tests/strategy/strats/hyperoptable_strategy.py +++ b/tests/strategy/strats/hyperoptable_strategy.py @@ -1,13 +1,13 @@ # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement from pandas import DataFrame -from strategy_test_v2 import StrategyTestV2 +from strategy_test_v3 import StrategyTestV3 import freqtrade.vendor.qtpylib.indicators as qtpylib from freqtrade.strategy import BooleanParameter, DecimalParameter, IntParameter, RealParameter -class HyperoptableStrategy(StrategyTestV2): +class HyperoptableStrategy(StrategyTestV3): """ Default Strategy provided by freqtrade bot. Please do not modify this strategy, it's intended for internal use only. diff --git a/tests/strategy/strats/hyperoptable_strategy_v2.py b/tests/strategy/strats/hyperoptable_strategy_v2.py new file mode 100644 index 000000000..94a15b456 --- /dev/null +++ b/tests/strategy/strats/hyperoptable_strategy_v2.py @@ -0,0 +1,54 @@ +# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement + +from strategy_test_v2 import StrategyTestV2 + +from freqtrade.strategy import BooleanParameter, DecimalParameter, IntParameter, RealParameter + + +class HyperoptableStrategyV2(StrategyTestV2): + """ + Default Strategy provided by freqtrade bot. + Please do not modify this strategy, it's intended for internal use only. + Please look at the SampleStrategy in the user_data/strategy directory + or strategy repository https://github.com/freqtrade/freqtrade-strategies + for samples and inspiration. + """ + + buy_params = { + 'buy_rsi': 35, + # Intentionally not specified, so "default" is tested + # 'buy_plusdi': 0.4 + } + + sell_params = { + 'sell_rsi': 74, + 'sell_minusdi': 0.4 + } + + buy_plusdi = RealParameter(low=0, high=1, default=0.5, space='buy') + sell_rsi = IntParameter(low=50, high=100, default=70, space='sell') + sell_minusdi = DecimalParameter(low=0, high=1, default=0.5001, decimals=3, space='sell', + load=False) + protection_enabled = BooleanParameter(default=True) + protection_cooldown_lookback = IntParameter([0, 50], default=30) + + @property + def protections(self): + prot = [] + if self.protection_enabled.value: + prot.append({ + "method": "CooldownPeriod", + "stop_duration_candles": self.protection_cooldown_lookback.value + }) + return prot + + bot_loop_started = False + + def bot_loop_start(self): + self.bot_loop_started = True + + def bot_start(self, **kwargs) -> None: + """ + Parameters can also be defined here ... + """ + self.buy_rsi = IntParameter([0, 50], default=30, space='buy') diff --git a/tests/strategy/test_interface.py b/tests/strategy/test_interface.py index dca87e724..f6996a7a2 100644 --- a/tests/strategy/test_interface.py +++ b/tests/strategy/test_interface.py @@ -916,7 +916,7 @@ def test_hyperopt_parameters(): def test_auto_hyperopt_interface(default_conf): - default_conf.update({'strategy': 'HyperoptableStrategy'}) + default_conf.update({'strategy': 'HyperoptableStrategyV2'}) PairLocks.timeframe = default_conf['timeframe'] strategy = StrategyResolver.load_strategy(default_conf) strategy.ft_bot_start() diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py index 666ae2b05..bdfcf3211 100644 --- a/tests/strategy/test_strategy_loading.py +++ b/tests/strategy/test_strategy_loading.py @@ -34,7 +34,7 @@ def test_search_all_strategies_no_failed(): directory = Path(__file__).parent / "strats" strategies = StrategyResolver.search_all_objects(directory, enum_failed=False) assert isinstance(strategies, list) - assert len(strategies) == 6 + assert len(strategies) == 7 assert isinstance(strategies[0], dict) @@ -42,10 +42,10 @@ def test_search_all_strategies_with_failed(): directory = Path(__file__).parent / "strats" strategies = StrategyResolver.search_all_objects(directory, enum_failed=True) assert isinstance(strategies, list) - assert len(strategies) == 7 + assert len(strategies) == 8 # with enum_failed=True search_all_objects() shall find 2 good strategies # and 1 which fails to load - assert len([x for x in strategies if x['class'] is not None]) == 6 + assert len([x for x in strategies if x['class'] is not None]) == 7 assert len([x for x in strategies if x['class'] is None]) == 1 From 2e642593e5e737ab87c3097574a4cb8def66f448 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 11:23:37 +0200 Subject: [PATCH 102/220] Update formatting of hyperopt_conf fixture --- tests/optimize/conftest.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/optimize/conftest.py b/tests/optimize/conftest.py index 8a9e0cbf0..9eb3a88cc 100644 --- a/tests/optimize/conftest.py +++ b/tests/optimize/conftest.py @@ -18,11 +18,11 @@ def hyperopt_conf(default_conf): 'runmode': RunMode.HYPEROPT, 'strategy': 'HyperoptableStrategy', 'hyperopt_loss': 'ShortTradeDurHyperOptLoss', - 'hyperopt_path': str(Path(__file__).parent / 'hyperopts'), - 'epochs': 1, - 'timerange': None, - 'spaces': ['default'], - 'hyperopt_jobs': 1, + 'hyperopt_path': str(Path(__file__).parent / 'hyperopts'), + 'epochs': 1, + 'timerange': None, + 'spaces': ['default'], + 'hyperopt_jobs': 1, 'hyperopt_min_trades': 1, }) return hyperconf From e53e53087491081b4b0f7e6f2f6c3afcd5ddefec Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 11:32:43 +0200 Subject: [PATCH 103/220] Add test showing broken inheritance hyperopt --- tests/optimize/test_hyperopt.py | 36 ++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 1ad8b33cf..fb5593ed2 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -855,7 +855,7 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None: 'strategy': 'HyperoptableStrategy', 'user_data_dir': Path(tmpdir), 'hyperopt_random_state': 42, - 'spaces': ['all'] + 'spaces': ['all'], }) hyperopt = Hyperopt(hyperopt_conf) hyperopt.backtesting.exchange.get_max_leverage = MagicMock(return_value=1.0) @@ -883,6 +883,40 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None: hyperopt.get_optimizer([], 2) +def test_in_strategy_auto_hyperopt_with_parallel(mocker, hyperopt_conf, tmpdir, fee) -> None: + # patch_exchange(mocker) + # TODO: This reaches out to the exchange! + mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) + (Path(tmpdir) / 'hyperopt_results').mkdir(parents=True) + # No hyperopt needed + hyperopt_conf.update({ + 'strategy': 'HyperoptableStrategy', + 'user_data_dir': Path(tmpdir), + 'hyperopt_random_state': 42, + 'spaces': ['all'], + # Enforce parallelity + 'epochs': 2, + 'hyperopt_jobs': 2, + 'fee': fee.return_value, + }) + hyperopt = Hyperopt(hyperopt_conf) + hyperopt.backtesting.exchange.get_max_leverage = lambda *x, **xx: 1.0 + assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto) + assert isinstance(hyperopt.backtesting.strategy.buy_rsi, IntParameter) + assert hyperopt.backtesting.strategy.bot_loop_started is True + + assert hyperopt.backtesting.strategy.buy_rsi.in_space is True + assert hyperopt.backtesting.strategy.buy_rsi.value == 35 + assert hyperopt.backtesting.strategy.sell_rsi.value == 74 + assert hyperopt.backtesting.strategy.protection_cooldown_lookback.value == 30 + buy_rsi_range = hyperopt.backtesting.strategy.buy_rsi.range + assert isinstance(buy_rsi_range, range) + # Range from 0 - 50 (inclusive) + assert len(list(buy_rsi_range)) == 51 + + hyperopt.start() + + def test_SKDecimal(): space = SKDecimal(1, 2, decimals=2) assert 1.5 in space From 40e2da10f35f7b2769df9278d050f912d2650a39 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 11:05:58 +0200 Subject: [PATCH 104/220] Add hypeorpt cloudpickle magic closes #7078 --- freqtrade/optimize/hyperopt.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 7c7493590..566412f29 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -6,6 +6,7 @@ This module contains the hyperopt logic import logging import random +import sys import warnings from datetime import datetime, timezone from math import ceil @@ -17,6 +18,7 @@ import rapidjson from colorama import Fore, Style from colorama import init as colorama_init from joblib import Parallel, cpu_count, delayed, dump, load, wrap_non_picklable_objects +from joblib.externals import cloudpickle from pandas import DataFrame from freqtrade.constants import DATETIME_PRINT_FORMAT, FTHYPT_FILEVERSION, LAST_BT_RESULT_FN @@ -87,6 +89,7 @@ class Hyperopt: self.backtesting._set_strategy(self.backtesting.strategylist[0]) self.custom_hyperopt.strategy = self.backtesting.strategy + self.hyperopt_pickle_magic(self.backtesting.strategy.__class__.__bases__) self.custom_hyperoptloss: IHyperOptLoss = HyperOptLossResolver.load_hyperoptloss( self.config) self.calculate_loss = self.custom_hyperoptloss.hyperopt_loss_function @@ -137,6 +140,17 @@ class Hyperopt: logger.info(f"Removing `{p}`.") p.unlink() + def hyperopt_pickle_magic(self, bases) -> None: + """ + Hyperopt magic to allow strategy inheritance across files. + For this to properly work, we need to register the module of the imported class + to pickle as value. + """ + for modules in bases: + if modules.__name__ != 'IStrategy': + cloudpickle.register_pickle_by_value(sys.modules[modules.__module__]) + self.hyperopt_pickle_magic(modules.__bases__) + def _get_params_dict(self, dimensions: List[Dimension], raw_params: List[Any]) -> Dict: # Ensure the number of dimensions match From 7c4dd4c48c7257f433669522ff1bd14be9d8133a Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 15 Jul 2022 09:54:53 +0200 Subject: [PATCH 105/220] Support fee cost as string closes #7056 --- freqtrade/exchange/exchange.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index cd13964c4..f6b85436d 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1646,7 +1646,7 @@ class Exchange: fee_curr = fee.get('currency') if fee_curr is None: return None - fee_cost = fee['cost'] + fee_cost = float(fee['cost']) if self._ft_has['fee_cost_in_contracts']: # Convert cost via "contracts" conversion fee_cost = self._contracts_to_amount(symbol, fee['cost']) @@ -1654,7 +1654,7 @@ class Exchange: # Calculate fee based on order details if fee_curr == self.get_pair_base_currency(symbol): # Base currency - divide by amount - return round(fee['cost'] / amount, 8) + return round(fee_cost / amount, 8) elif fee_curr == self.get_pair_quote_currency(symbol): # Quote currency - divide by cost return round(fee_cost / cost, 8) if cost else None @@ -1685,7 +1685,7 @@ class Exchange: :param amount: Amount of the order :return: Tuple with cost, currency, rate of the given fee dict """ - return (fee['cost'], + return (float(fee['cost']), fee['currency'], self.calculate_fee_rate( fee, From 7b8a5585dd6b2cb7cbfc550c30d2353af3869616 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 15 Jul 2022 14:35:49 +0200 Subject: [PATCH 106/220] Fetch 2ndary stoploss order once the order triggered. --- freqtrade/exchange/gateio.py | 14 +++++++++++++- tests/exchange/test_gateio.py | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index b9de212de..f46508022 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -97,11 +97,23 @@ class Gateio(Exchange): return trades def fetch_stoploss_order(self, order_id: str, pair: str, params: Dict = {}) -> Dict: - return self.fetch_order( + order = self.fetch_order( order_id=order_id, pair=pair, params={'stop': True} ) + if self.trading_mode == TradingMode.FUTURES: + if order['status'] == 'closed': + # Places a real order - which we need to fetch explicitly. + new_orderid = order.get('info', {}).get('trade_id') + if new_orderid: + order1 = self.fetch_order(order_id=new_orderid, pair=pair, params=params) + order1['id_stop'] = order1['id'] + order1['id'] = order_id + order1['stopPrice'] = order.get('stopPrice') + + return order1 + return order def cancel_stoploss_order(self, order_id: str, pair: str, params: Dict = {}) -> Dict: return self.cancel_order( diff --git a/tests/exchange/test_gateio.py b/tests/exchange/test_gateio.py index cbd4776fb..dabdbba65 100644 --- a/tests/exchange/test_gateio.py +++ b/tests/exchange/test_gateio.py @@ -53,6 +53,25 @@ def test_fetch_stoploss_order_gateio(default_conf, mocker): assert fetch_order_mock.call_args_list[0][1]['pair'] == 'ETH/BTC' assert fetch_order_mock.call_args_list[0][1]['params'] == {'stop': True} + default_conf['trading_mode'] = 'futures' + default_conf['margin_mode'] = 'isolated' + + exchange = get_patched_exchange(mocker, default_conf, id='gateio') + + exchange.fetch_order = MagicMock(return_value={ + 'status': 'closed', + 'id': '1234', + 'stopPrice': 5.62, + 'info': { + 'trade_id': '222555' + } + }) + + exchange.fetch_stoploss_order('1234', 'ETH/BTC') + assert exchange.fetch_order.call_count == 2 + assert exchange.fetch_order.call_args_list[0][1]['order_id'] == '1234' + assert exchange.fetch_order.call_args_list[1][1]['order_id'] == '222555' + def test_cancel_stoploss_order_gateio(default_conf, mocker): exchange = get_patched_exchange(mocker, default_conf, id='gateio') From 415780a4fe1c37785ebe26c398762f467ed5b570 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 11:58:38 +0200 Subject: [PATCH 107/220] gateio order cost is not in contracts closes #7081 --- freqtrade/exchange/exchange.py | 3 ++- freqtrade/exchange/gateio.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index f6b85436d..7ac45bcc9 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -79,6 +79,7 @@ class Exchange: "ccxt_futures_name": "swap", "fee_cost_in_contracts": False, # Fee cost needs contract conversion "needs_trading_fees": False, # use fetch_trading_fees to cache fees + "order_props_in_contracts": ['amount', 'cost', 'filled', 'remaining'], } _ft_has: Dict = {} _ft_has_futures: Dict = {} @@ -423,7 +424,7 @@ class Exchange: if 'symbol' in order and order['symbol'] is not None: contract_size = self._get_contract_size(order['symbol']) if contract_size != 1: - for prop in ['amount', 'cost', 'filled', 'remaining']: + for prop in self._ft_has.get('order_props_in_contracts', []): if prop in order and order[prop] is not None: order[prop] = order[prop] * contract_size return order diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index f46508022..c049ce4cc 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -34,6 +34,7 @@ class Gateio(Exchange): _ft_has_futures: Dict = { "needs_trading_fees": True, "fee_cost_in_contracts": False, # Set explicitly to false for clarity + "order_props_in_contracts": ['amount', 'filled', 'remaining'], } _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ From ed64e4299bb6b728513f3063a56e6fceda777e90 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 12:52:35 +0200 Subject: [PATCH 108/220] Stoploss orders should also be eligible to update closed fees --- freqtrade/exchange/gateio.py | 8 +++++++- freqtrade/freqtradebot.py | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index c049ce4cc..6df3425d2 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -1,12 +1,13 @@ """ Gate.io exchange subclass """ import logging from datetime import datetime -from typing import Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple from freqtrade.constants import BuySell from freqtrade.enums import MarginMode, TradingMode from freqtrade.exceptions import OperationalException from freqtrade.exchange import Exchange +from freqtrade.misc import safe_value_fallback2 logger = logging.getLogger(__name__) @@ -97,6 +98,11 @@ class Gateio(Exchange): } return trades + def get_order_id_conditional(self, order: Dict[str, Any]) -> str: + if self.trading_mode == TradingMode.FUTURES: + return safe_value_fallback2(order, order, 'id_stop', 'id') + return order['id'] + def fetch_stoploss_order(self, order_id: str, pair: str, params: Dict = {}) -> Dict: order = self.fetch_order( order_id=order_id, diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 469bfda7e..2007f9b4e 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -332,6 +332,8 @@ class FreqtradeBot(LoggingMixin): if not trade.is_open and not trade.fee_updated(trade.exit_side): # Get sell fee order = trade.select_order(trade.exit_side, False) + if not order: + order = trade.select_order('stoploss', False) if order: logger.info( f"Updating {trade.exit_side}-fee on trade {trade}" From d03dfb393497fe63b042ebd22d932a0bcabcbfec Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 13:12:50 +0200 Subject: [PATCH 109/220] Oder cost is real cost (including leverage) --- freqtrade/exchange/exchange.py | 2 +- tests/exchange/test_exchange.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 7ac45bcc9..43fbbe28b 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -822,7 +822,7 @@ class Exchange: 'price': rate, 'average': rate, 'amount': _amount, - 'cost': _amount * rate / leverage, + 'cost': _amount * rate, 'type': ordertype, 'side': side, 'filled': 0, diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index acd48b3fd..bf4f44440 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1135,7 +1135,7 @@ def test_create_dry_run_order(default_conf, mocker, side, exchange_name, leverag assert order["symbol"] == "ETH/BTC" assert order["amount"] == 1 assert order["leverage"] == leverage - assert order["cost"] == 1 * 200 / leverage + assert order["cost"] == 1 * 200 @pytest.mark.parametrize("side,startprice,endprice", [ From 357000c478a078a22d09345887ee9955d41b9abe Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 13:27:13 +0200 Subject: [PATCH 110/220] Extract exchange validation to separate method --- freqtrade/exchange/exchange.py | 28 +++++++++++++++------------- tests/conftest.py | 5 +---- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index cd13964c4..505d02e8c 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -175,23 +175,11 @@ class Exchange: logger.info(f'Using Exchange "{self.name}"') if validate: - # Check if timeframe is available - self.validate_timeframes(config.get('timeframe')) - # Initial markets load self._load_markets() - - # Check if all pairs are available - self.validate_stakecurrency(config['stake_currency']) - if not exchange_config.get('skip_pair_validation'): - self.validate_pairs(config['exchange']['pair_whitelist']) - self.validate_ordertypes(config.get('order_types', {})) - self.validate_order_time_in_force(config.get('order_time_in_force', {})) + self.validate_config(config) self.required_candle_call_count = self.validate_required_startup_candles( config.get('startup_candle_count', 0), config.get('timeframe', '')) - self.validate_trading_mode_and_margin_mode(self.trading_mode, self.margin_mode) - self.validate_pricing(config['exit_pricing']) - self.validate_pricing(config['entry_pricing']) # Converts the interval provided in minutes in config to seconds self.markets_refresh_interval: int = exchange_config.get( @@ -214,6 +202,20 @@ class Exchange: logger.info("Closing async ccxt session.") self.loop.run_until_complete(self._api_async.close()) + def validate_config(self, config): + # Check if timeframe is available + self.validate_timeframes(config.get('timeframe')) + + # Check if all pairs are available + self.validate_stakecurrency(config['stake_currency']) + if not config['exchange'].get('skip_pair_validation'): + self.validate_pairs(config['exchange']['pair_whitelist']) + self.validate_ordertypes(config.get('order_types', {})) + self.validate_order_time_in_force(config.get('order_time_in_force', {})) + self.validate_trading_mode_and_margin_mode(self.trading_mode, self.margin_mode) + self.validate_pricing(config['exit_pricing']) + self.validate_pricing(config['entry_pricing']) + def _init_ccxt(self, exchange_config: Dict[str, Any], ccxt_module: CcxtModuleType = ccxt, ccxt_kwargs: Dict = {}) -> ccxt.Exchange: """ diff --git a/tests/conftest.py b/tests/conftest.py index 0cf32545f..3158e9ede 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -112,11 +112,8 @@ def patch_exchange( mock_supported_modes=True ) -> None: mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock(return_value={})) - mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock()) + mocker.patch('freqtrade.exchange.Exchange.validate_config', MagicMock()) mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) - mocker.patch('freqtrade.exchange.Exchange.validate_ordertypes', MagicMock()) - mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency', MagicMock()) - mocker.patch('freqtrade.exchange.Exchange.validate_pricing') mocker.patch('freqtrade.exchange.Exchange.id', PropertyMock(return_value=id)) mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value=id.title())) mocker.patch('freqtrade.exchange.Exchange.precisionMode', PropertyMock(return_value=2)) From bf07d8fe879ca592db74b1bf61bb59cd8441bee4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 13:57:04 +0200 Subject: [PATCH 111/220] Update test to properly patch/mock exchange --- tests/optimize/test_hyperopt.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index fb5593ed2..0f615b7a3 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -1,7 +1,7 @@ # pragma pylint: disable=missing-docstring,W0212,C0103 from datetime import datetime, timedelta from pathlib import Path -from unittest.mock import ANY, MagicMock +from unittest.mock import ANY, MagicMock, PropertyMock import pandas as pd import pytest @@ -18,8 +18,8 @@ from freqtrade.optimize.hyperopt_tools import HyperoptTools from freqtrade.optimize.optimize_reports import generate_strategy_stats from freqtrade.optimize.space import SKDecimal from freqtrade.strategy import IntParameter -from tests.conftest import (CURRENT_TEST_STRATEGY, get_args, log_has, log_has_re, patch_exchange, - patched_configuration_load_config_file) +from tests.conftest import (CURRENT_TEST_STRATEGY, get_args, get_markets, log_has, log_has_re, + patch_exchange, patched_configuration_load_config_file) def generate_result_metrics(): @@ -884,9 +884,11 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None: def test_in_strategy_auto_hyperopt_with_parallel(mocker, hyperopt_conf, tmpdir, fee) -> None: - # patch_exchange(mocker) - # TODO: This reaches out to the exchange! + mocker.patch('freqtrade.exchange.Exchange.validate_config', MagicMock()) mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) + mocker.patch('freqtrade.exchange.Exchange._load_markets') + mocker.patch('freqtrade.exchange.Exchange.markets', + PropertyMock(return_value=get_markets())) (Path(tmpdir) / 'hyperopt_results').mkdir(parents=True) # No hyperopt needed hyperopt_conf.update({ @@ -901,6 +903,9 @@ def test_in_strategy_auto_hyperopt_with_parallel(mocker, hyperopt_conf, tmpdir, }) hyperopt = Hyperopt(hyperopt_conf) hyperopt.backtesting.exchange.get_max_leverage = lambda *x, **xx: 1.0 + hyperopt.backtesting.exchange.get_min_pair_stake_amount = lambda *x, **xx: 1.0 + hyperopt.backtesting.exchange.get_max_pair_stake_amount = lambda *x, **xx: 100.0 + assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto) assert isinstance(hyperopt.backtesting.strategy.buy_rsi, IntParameter) assert hyperopt.backtesting.strategy.bot_loop_started is True From 8b2535a8da3eabbbb53a70eeebb6348afaf0edd6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 15:42:17 +0200 Subject: [PATCH 112/220] Update Typing for fees --- freqtrade/constants.py | 1 + freqtrade/exchange/exchange.py | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/freqtrade/constants.py b/freqtrade/constants.py index ce7c0ff83..6d74ceafd 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -542,3 +542,4 @@ TradeList = List[List] LongShort = Literal['long', 'short'] EntryExit = Literal['entry', 'exit'] BuySell = Literal['buy', 'sell'] +MakerTaker = Literal['maker', 'taker'] diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index db7a8ce41..2deb2b70d 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -20,7 +20,7 @@ from ccxt import ROUND_DOWN, ROUND_UP, TICK_SIZE, TRUNCATE, Precise, decimal_to_ from pandas import DataFrame from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES, BuySell, - EntryExit, ListPairsWithTimeframes, PairWithTimeframe) + EntryExit, ListPairsWithTimeframes, MakerTaker, PairWithTimeframe) from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list from freqtrade.enums import OPTIMIZE_MODES, CandleType, MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError, @@ -870,7 +870,8 @@ class Exchange: 'filled': _amount, 'cost': (dry_order['amount'] * average) / leverage }) - dry_order = self.add_dry_order_fee(pair, dry_order, self.taker_or_maker('entry')) + # market orders will always incurr taker fees + dry_order = self.add_dry_order_fee(pair, dry_order, 'taker') dry_order = self.check_dry_limit_order_filled(dry_order) @@ -882,7 +883,7 @@ class Exchange: self, pair: str, dry_order: Dict[str, Any], - taker_or_maker: Literal['taker', 'maker'], + taker_or_maker: MakerTaker, ) -> Dict[str, Any]: dry_order.update({ 'fee': { @@ -970,7 +971,7 @@ class Exchange: }) enter_long = not order['is_short'] and order['side'] == 'buy' enter_short = order['is_short'] and order['side'] == 'sell' - entry_or_exit: Literal['entry', 'exit'] = ( + entry_or_exit: EntryExit = ( 'entry' if (enter_short or enter_long) else 'exit' ) self.add_dry_order_fee( @@ -1635,7 +1636,7 @@ class Exchange: @retrier def get_fee(self, symbol: str, type: str = '', side: str = '', amount: float = 1, - price: float = 1, taker_or_maker: str = 'maker') -> float: + price: float = 1, taker_or_maker: MakerTaker = 'maker') -> float: try: if self._config['dry_run'] and self._config.get('fee', None) is not None: return self._config['fee'] From 4172f92bfc492a140103d79027fc326348183cc0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 17:03:45 +0200 Subject: [PATCH 113/220] simplify dry-run taker/maker selection --- freqtrade/exchange/exchange.py | 33 ++++--------------------- tests/exchange/test_exchange.py | 43 ++++++++++++--------------------- 2 files changed, 20 insertions(+), 56 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 2deb2b70d..efb33ee74 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -811,26 +811,6 @@ class Exchange: # Dry-run methods - def taker_or_maker( - self, - order_reason: Literal['entry', 'exit', 'stoploss'], # TODO: stoploss - ): - order_type = self._config['order_types'][order_reason] - if order_type == 'market' or order_reason == 'stoploss': - return 'taker' - else: - return ( - 'maker' if ( - ( - order_reason == 'entry' and - self._config['entry_pricing']['price_side'] == 'same' - ) or ( - order_reason == 'exit' and - self._config['exit_pricing']['price_side'] == 'same' - ) - ) else 'taker' - ) - def create_dry_run_order(self, pair: str, ordertype: str, side: str, amount: float, rate: float, leverage: float, params: Dict = {}, stop_loss: bool = False) -> Dict[str, Any]: @@ -873,7 +853,7 @@ class Exchange: # market orders will always incurr taker fees dry_order = self.add_dry_order_fee(pair, dry_order, 'taker') - dry_order = self.check_dry_limit_order_filled(dry_order) + dry_order = self.check_dry_limit_order_filled(dry_order, immediate=True) self._dry_run_open_orders[dry_order["id"]] = dry_order # Copy order and close it - so the returned order is open unless it's a market order @@ -955,7 +935,8 @@ class Exchange: pass return False - def check_dry_limit_order_filled(self, order: Dict[str, Any]) -> Dict[str, Any]: + def check_dry_limit_order_filled( + self, order: Dict[str, Any], immediate: bool = False) -> Dict[str, Any]: """ Check dry-run limit order fill and update fee (if it filled). """ @@ -969,15 +950,11 @@ class Exchange: 'filled': order['amount'], 'remaining': 0, }) - enter_long = not order['is_short'] and order['side'] == 'buy' - enter_short = order['is_short'] and order['side'] == 'sell' - entry_or_exit: EntryExit = ( - 'entry' if (enter_short or enter_long) else 'exit' - ) + self.add_dry_order_fee( pair, order, - self.taker_or_maker(entry_or_exit) + 'taker' if immediate else 'maker', ) return order diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 0c4df8f5a..ff8b4b40c 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1160,23 +1160,33 @@ def test_create_dry_run_order_fees( price_side, fee, ): - default_conf[f"{order_reason}_pricing"]["price_side"] = "same" - default_conf["order_types"][order_reason] = order_type mocker.patch( 'freqtrade.exchange.Exchange.get_fee', - lambda symbol, taker_or_maker: 2.0 if taker_or_maker == 'taker' else 1.0 + side_effect=lambda symbol, taker_or_maker: 2.0 if taker_or_maker == 'taker' else 1.0 ) + mocker.patch('freqtrade.exchange.Exchange._is_dry_limit_order_filled', + return_value=price_side == 'other') exchange = get_patched_exchange(mocker, default_conf) order = exchange.create_dry_run_order( - pair='ADA/USDT', + pair='LTC/USDT', ordertype=order_type, side=side, amount=10, rate=2.0, + leverage=1.0 ) + if price_side == 'other' or order_type == 'market': + assert order['fee']['rate'] == fee + return + else: + assert order['fee'] is None - assert order['ft_fee_base'] == fee + mocker.patch('freqtrade.exchange.Exchange._is_dry_limit_order_filled', + return_value=price_side != 'other') + + order1 = exchange.fetch_dry_run_order(order['id']) + assert order1['fee']['rate'] == fee @pytest.mark.parametrize("side,startprice,endprice", [ @@ -5101,26 +5111,3 @@ def test_stoploss_contract_size(mocker, default_conf, contract_size, order_amoun assert order['cost'] == 100 assert order['filled'] == 100 assert order['remaining'] == 100 - - -@pytest.mark.parametrize('order_reason,price_side,order_type,taker_or_maker', [ - ("entry", "same", "limit", "maker"), - ("exit", "same", "limit", "maker"), - ("entry", "other", "limit", "taker"), - ("exit", "other", "limit", "taker"), - ("stoploss", "same", "limit", "taker"), - ("stoploss", "other", "limit", "taker"), - ("entry", "same", "market", "taker"), - ("exit", "same", "market", "taker"), - ("entry", "other", "market", "taker"), - ("exit", "other", "market", "taker"), - ("stoploss", "same", "market", "taker"), - ("stoploss", "other", "market", "taker"), -]) -def test_taker_or_maker(mocker, default_conf, order_reason, price_side, order_type, taker_or_maker): - if order_reason != 'stoploss': - default_conf[f"{order_reason}_pricing"]["price_side"] = price_side - default_conf["order_types"] = {} - default_conf["order_types"][order_reason] = order_type - exchange = get_patched_exchange(mocker, default_conf) - assert exchange.taker_or_maker(order_reason) == taker_or_maker From 423af371c0ec8822f03cd9f10528e2c0d58e3512 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 17:59:05 +0200 Subject: [PATCH 114/220] Simplify calculation by calling "get_fee" only once --- freqtrade/exchange/exchange.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index efb33ee74..a430cdac5 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -865,11 +865,12 @@ class Exchange: dry_order: Dict[str, Any], taker_or_maker: MakerTaker, ) -> Dict[str, Any]: + fee = self.get_fee(pair, taker_or_maker=taker_or_maker) dry_order.update({ 'fee': { 'currency': self.get_pair_quote_currency(pair), - 'cost': dry_order['cost'] * self.get_fee(pair, taker_or_maker=taker_or_maker), - 'rate': self.get_fee(pair, taker_or_maker=taker_or_maker) + 'cost': dry_order['cost'] * fee, + 'rate': fee } }) return dry_order From 9347677c6061648517767dce5916dcf0394c71e6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 19:33:26 +0200 Subject: [PATCH 115/220] Uppdate pricecontours test to not recreate backtesting every loop in hopes to fix random failure --- tests/optimize/test_backtesting.py | 61 ++++++++++++++++++------------ 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index 6912184aa..0b964c54a 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -90,28 +90,6 @@ def load_data_test(what, testdatadir): fill_missing=True)} -def simple_backtest(config, contour, mocker, testdatadir) -> None: - patch_exchange(mocker) - config['timeframe'] = '1m' - backtesting = Backtesting(config) - backtesting._set_strategy(backtesting.strategylist[0]) - - data = load_data_test(contour, testdatadir) - processed = backtesting.strategy.advise_all_indicators(data) - min_date, max_date = get_timerange(processed) - assert isinstance(processed, dict) - results = backtesting.backtest( - processed=processed, - start_date=min_date, - end_date=max_date, - max_open_trades=1, - position_stacking=False, - enable_protections=config.get('enable_protections', False), - ) - # results :: - return results - - # FIX: fixturize this? def _make_backtest_conf(mocker, datadir, conf=None, pair='UNITTEST/BTC'): data = history.load_data(datadir=datadir, timeframe='1m', pairs=[pair]) @@ -942,6 +920,7 @@ def test_backtest_dataprovider_analyzed_df(default_conf, fee, mocker, testdatadi def test_backtest_pricecontours_protections(default_conf, fee, mocker, testdatadir) -> None: # While this test IS a copy of test_backtest_pricecontours, it's needed to ensure # results do not carry-over to the next run, which is not given by using parametrize. + patch_exchange(mocker) default_conf['protections'] = [ { "method": "CooldownPeriod", @@ -949,6 +928,7 @@ def test_backtest_pricecontours_protections(default_conf, fee, mocker, testdatad }] default_conf['enable_protections'] = True + default_conf['timeframe'] = '1m' mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) @@ -959,12 +939,27 @@ def test_backtest_pricecontours_protections(default_conf, fee, mocker, testdatad ['sine', 9], ['raise', 10], ] + backtesting = Backtesting(default_conf) + backtesting._set_strategy(backtesting.strategylist[0]) + # While entry-signals are unrealistic, running backtesting # over and over again should not cause different results for [contour, numres] in tests: # Debug output for random test failure print(f"{contour}, {numres}") - assert len(simple_backtest(default_conf, contour, mocker, testdatadir)['results']) == numres + data = load_data_test(contour, testdatadir) + processed = backtesting.strategy.advise_all_indicators(data) + min_date, max_date = get_timerange(processed) + assert isinstance(processed, dict) + results = backtesting.backtest( + processed=processed, + start_date=min_date, + end_date=max_date, + max_open_trades=1, + position_stacking=False, + enable_protections=default_conf.get('enable_protections', False), + ) + assert len(results['results']) == numres @pytest.mark.parametrize('protections,contour,expected', [ @@ -990,7 +985,25 @@ def test_backtest_pricecontours(default_conf, fee, mocker, testdatadir, mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) # While entry-signals are unrealistic, running backtesting # over and over again should not cause different results - assert len(simple_backtest(default_conf, contour, mocker, testdatadir)['results']) == expected + + patch_exchange(mocker) + default_conf['timeframe'] = '1m' + backtesting = Backtesting(default_conf) + backtesting._set_strategy(backtesting.strategylist[0]) + + data = load_data_test(contour, testdatadir) + processed = backtesting.strategy.advise_all_indicators(data) + min_date, max_date = get_timerange(processed) + assert isinstance(processed, dict) + results = backtesting.backtest( + processed=processed, + start_date=min_date, + end_date=max_date, + max_open_trades=1, + position_stacking=False, + enable_protections=default_conf.get('enable_protections', False), + ) + assert len(results['results']) == expected def test_backtest_clash_buy_sell(mocker, default_conf, testdatadir): From 05a5ae4fcfac1423a67b80411535a0b2ba07da27 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Jul 2022 22:28:46 +0200 Subject: [PATCH 116/220] Update plotting to use entry/exit terminology --- freqtrade/plot/plotting.py | 22 +++++++++++----------- tests/test_plotting.py | 36 ++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py index a64281156..f8e95300a 100644 --- a/freqtrade/plot/plotting.py +++ b/freqtrade/plot/plotting.py @@ -255,18 +255,18 @@ def plot_trades(fig, trades: pd.DataFrame) -> make_subplots: """ # Trades can be empty if trades is not None and len(trades) > 0: - # Create description for sell summarizing the trade + # Create description for exit summarizing the trade trades['desc'] = trades.apply( lambda row: f"{row['profit_ratio']:.2%}, " + (f"{row['enter_tag']}, " if row['enter_tag'] is not None else "") + f"{row['exit_reason']}, " + f"{row['trade_duration']} min", axis=1) - trade_buys = go.Scatter( + trade_entries = go.Scatter( x=trades["open_date"], y=trades["open_rate"], mode='markers', - name='Trade buy', + name='Trade entry', text=trades["desc"], marker=dict( symbol='circle-open', @@ -277,12 +277,12 @@ def plot_trades(fig, trades: pd.DataFrame) -> make_subplots: ) ) - trade_sells = go.Scatter( + trade_exits = go.Scatter( x=trades.loc[trades['profit_ratio'] > 0, "close_date"], y=trades.loc[trades['profit_ratio'] > 0, "close_rate"], text=trades.loc[trades['profit_ratio'] > 0, "desc"], mode='markers', - name='Sell - Profit', + name='Exit - Profit', marker=dict( symbol='square-open', size=11, @@ -290,12 +290,12 @@ def plot_trades(fig, trades: pd.DataFrame) -> make_subplots: color='green' ) ) - trade_sells_loss = go.Scatter( + trade_exits_loss = go.Scatter( x=trades.loc[trades['profit_ratio'] <= 0, "close_date"], y=trades.loc[trades['profit_ratio'] <= 0, "close_rate"], text=trades.loc[trades['profit_ratio'] <= 0, "desc"], mode='markers', - name='Sell - Loss', + name='Exit - Loss', marker=dict( symbol='square-open', size=11, @@ -303,9 +303,9 @@ def plot_trades(fig, trades: pd.DataFrame) -> make_subplots: color='red' ) ) - fig.add_trace(trade_buys, 1, 1) - fig.add_trace(trade_sells, 1, 1) - fig.add_trace(trade_sells_loss, 1, 1) + fig.add_trace(trade_entries, 1, 1) + fig.add_trace(trade_exits, 1, 1) + fig.add_trace(trade_exits_loss, 1, 1) else: logger.warning("No trades found.") return fig @@ -444,7 +444,7 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra Generate the graph from the data generated by Backtesting or from DB Volume will always be ploted in row2, so Row 1 and 3 are to our disposal for custom indicators :param pair: Pair to Display on the graph - :param data: OHLCV DataFrame containing indicators and buy/sell signals + :param data: OHLCV DataFrame containing indicators and entry/exit signals :param trades: All trades created :param indicators1: List containing Main plot indicators :param indicators2: List containing Sub plot indicators diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 9ee7a75c6..52e96e477 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -72,7 +72,7 @@ def test_add_indicators(default_conf, testdatadir, caplog): strategy = StrategyResolver.load_strategy(default_conf) - # Generate buy/sell signals and indicators + # Generate entry/exit signals and indicators data = strategy.analyze_ticker(data, {'pair': pair}) fig = generate_empty_figure() @@ -113,7 +113,7 @@ def test_add_areas(default_conf, testdatadir, caplog): ind_plain = {"macd": {"fill_to": "macdhist"}} strategy = StrategyResolver.load_strategy(default_conf) - # Generate buy/sell signals and indicators + # Generate entry/exit signals and indicators data = strategy.analyze_ticker(data, {'pair': pair}) fig = generate_empty_figure() @@ -165,24 +165,24 @@ def test_plot_trades(testdatadir, caplog): fig = plot_trades(fig, trades) figure = fig1.layout.figure - # Check buys - color, should be in first graph, ... - trade_buy = find_trace_in_fig_data(figure.data, 'Trade buy') - assert isinstance(trade_buy, go.Scatter) - assert trade_buy.yaxis == 'y' - assert len(trades) == len(trade_buy.x) - assert trade_buy.marker.color == 'cyan' - assert trade_buy.marker.symbol == 'circle-open' - assert trade_buy.text[0] == '3.99%, buy_tag, roi, 15 min' + # Check entry - color, should be in first graph, ... + trade_entries = find_trace_in_fig_data(figure.data, 'Trade entry') + assert isinstance(trade_entries, go.Scatter) + assert trade_entries.yaxis == 'y' + assert len(trades) == len(trade_entries.x) + assert trade_entries.marker.color == 'cyan' + assert trade_entries.marker.symbol == 'circle-open' + assert trade_entries.text[0] == '3.99%, buy_tag, roi, 15 min' - trade_sell = find_trace_in_fig_data(figure.data, 'Sell - Profit') - assert isinstance(trade_sell, go.Scatter) - assert trade_sell.yaxis == 'y' - assert len(trades.loc[trades['profit_ratio'] > 0]) == len(trade_sell.x) - assert trade_sell.marker.color == 'green' - assert trade_sell.marker.symbol == 'square-open' - assert trade_sell.text[0] == '3.99%, buy_tag, roi, 15 min' + trade_exit = find_trace_in_fig_data(figure.data, 'Exit - Profit') + assert isinstance(trade_exit, go.Scatter) + assert trade_exit.yaxis == 'y' + assert len(trades.loc[trades['profit_ratio'] > 0]) == len(trade_exit.x) + assert trade_exit.marker.color == 'green' + assert trade_exit.marker.symbol == 'square-open' + assert trade_exit.text[0] == '3.99%, buy_tag, roi, 15 min' - trade_sell_loss = find_trace_in_fig_data(figure.data, 'Sell - Loss') + trade_sell_loss = find_trace_in_fig_data(figure.data, 'Exit - Loss') assert isinstance(trade_sell_loss, go.Scatter) assert trade_sell_loss.yaxis == 'y' assert len(trades.loc[trades['profit_ratio'] <= 0]) == len(trade_sell_loss.x) From 46be1b8778c9729f16651c2b8f00ac78dd98de98 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 17 Jul 2022 07:21:42 +0200 Subject: [PATCH 117/220] Version bump ccxt to 1.90.88 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2bb3b4b75..49121a9da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.90.47 +ccxt==1.90.88 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.4 aiohttp==3.8.1 From 2c6fb617a6574ac9342fdbaa937938e581de525a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Jul 2022 03:01:23 +0000 Subject: [PATCH 118/220] Bump jsonschema from 4.6.2 to 4.7.2 Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.6.2 to 4.7.2. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.6.2...v4.7.2) --- updated-dependencies: - dependency-name: jsonschema 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 49121a9da..78a327988 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ arrow==1.2.2 cachetools==4.2.2 requests==2.28.1 urllib3==1.26.10 -jsonschema==4.6.2 +jsonschema==4.7.2 TA-Lib==0.4.24 technical==1.3.0 tabulate==0.8.10 From 5f820ab0a64a0ebe0152c74901cb890d8a8a0cd9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Jul 2022 03:01:26 +0000 Subject: [PATCH 119/220] Bump pytest-asyncio from 0.18.3 to 0.19.0 Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.18.3 to 0.19.0. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Changelog](https://github.com/pytest-dev/pytest-asyncio/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.18.3...v0.19.0) --- updated-dependencies: - dependency-name: pytest-asyncio 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 f2f77c2ba..ac7f4f619 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,7 +10,7 @@ flake8-tidy-imports==4.8.0 mypy==0.961 pre-commit==2.20.0 pytest==7.1.2 -pytest-asyncio==0.18.3 +pytest-asyncio==0.19.0 pytest-cov==3.0.0 pytest-mock==3.8.2 pytest-random-order==1.0.4 From cb63d5e3dfe9dc9b8275098ba8b7cf6dc446ac2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Jul 2022 03:01:31 +0000 Subject: [PATCH 120/220] Bump fastapi from 0.78.0 to 0.79.0 Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.78.0 to 0.79.0. - [Release notes](https://github.com/tiangolo/fastapi/releases) - [Commits](https://github.com/tiangolo/fastapi/compare/0.78.0...0.79.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 49121a9da..18c656bfb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,7 +34,7 @@ orjson==3.7.7 sdnotify==0.3.2 # API Server -fastapi==0.78.0 +fastapi==0.79.0 uvicorn==0.18.2 pyjwt==2.4.0 aiofiles==0.8.0 From f07ad7aa875a3c0c53de3c70b73330a90676d6c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Jul 2022 03:01:40 +0000 Subject: [PATCH 121/220] Bump ccxt from 1.90.88 to 1.90.89 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.90.88 to 1.90.89. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.90.88...1.90.89) --- 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 49121a9da..9c9973ee8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.90.88 +ccxt==1.90.89 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.4 aiohttp==3.8.1 From d2ef248781718ce27e3c59cad6539ba91adb01b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Jul 2022 03:01:43 +0000 Subject: [PATCH 122/220] Bump markdown from 3.3.7 to 3.4.1 Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.3.7 to 3.4.1. - [Release notes](https://github.com/Python-Markdown/markdown/releases) - [Commits](https://github.com/Python-Markdown/markdown/compare/3.3.7...3.4.1) --- updated-dependencies: - dependency-name: markdown dependency-type: direct:production update-type: version-update:semver-minor ... 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 22d92c65d..a5fe8b921 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,4 +1,4 @@ -markdown==3.3.7 +markdown==3.4.1 mkdocs==1.3.0 mkdocs-material==8.3.9 mdx_truly_sane_lists==1.2 From ea523136fc29cdf62a14c59e85edfe089ac03b1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Jul 2022 03:01:49 +0000 Subject: [PATCH 123/220] Bump types-requests from 2.28.0 to 2.28.1 Bumps [types-requests](https://github.com/python/typeshed) from 2.28.0 to 2.28.1. - [Release notes](https://github.com/python/typeshed/releases) - [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 f2f77c2ba..435cb9b1c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,6 +24,6 @@ nbconvert==6.5.0 # mypy types types-cachetools==5.2.1 types-filelock==3.2.7 -types-requests==2.28.0 +types-requests==2.28.1 types-tabulate==0.8.11 types-python-dateutil==2.8.18 From 0daa9d3e57bfa09f98c17d14258dd9fad32803dd Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 18 Jul 2022 07:56:41 +0200 Subject: [PATCH 124/220] Bump types-requests in pre-commit --- .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 59e7f6894..a23181c37 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: additional_dependencies: - types-cachetools==5.2.1 - types-filelock==3.2.7 - - types-requests==2.28.0 + - types-requests==2.28.1 - types-tabulate==0.8.11 - types-python-dateutil==2.8.18 # stages: [push] From 75e190ff1ddfecfd1796d99dbde4a060a18e96b7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 18 Jul 2022 20:15:07 +0200 Subject: [PATCH 125/220] Update sell-test without filled buy order --- tests/test_freqtradebot.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 4963e2b0a..e431e7ac3 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -2060,8 +2060,9 @@ def test_update_trade_state_orderexception(mocker, default_conf_usdt, caplog) -> @pytest.mark.parametrize("is_short", [False, True]) def test_update_trade_state_sell( - default_conf_usdt, trades_for_order, limit_order_open, limit_order, is_short, mocker, + default_conf_usdt, trades_for_order, limit_order_open, limit_order, is_short, mocker ): + buy_order = limit_order[entry_side(is_short)] open_order = limit_order_open[exit_side(is_short)] l_order = limit_order[exit_side(is_short)] mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order) @@ -2088,6 +2089,9 @@ def test_update_trade_state_sell( leverage=1, is_short=is_short, ) + order = Order.parse_from_ccxt_object(buy_order, 'LTC/ETH', entry_side(is_short)) + trade.orders.append(order) + order = Order.parse_from_ccxt_object(open_order, 'LTC/ETH', exit_side(is_short)) trade.orders.append(order) assert order.status == 'open' @@ -2787,6 +2791,7 @@ def test_manage_open_orders_partial( rpc_mock = patch_RPCManager(mocker) open_trade.is_short = is_short open_trade.leverage = leverage + open_trade.orders[0].ft_order_side = 'sell' if is_short else 'buy' limit_buy_order_old_partial['id'] = open_trade.open_order_id limit_buy_order_old_partial['side'] = 'sell' if is_short else 'buy' limit_buy_canceled = deepcopy(limit_buy_order_old_partial) @@ -2872,6 +2877,7 @@ def test_manage_open_orders_partial_except( limit_buy_order_old_partial_canceled, mocker ) -> None: open_trade.is_short = is_short + open_trade.orders[0].ft_order_side = 'sell' if is_short else 'buy' rpc_mock = patch_RPCManager(mocker) limit_buy_order_old_partial_canceled['id'] = open_trade.open_order_id limit_buy_order_old_partial['id'] = open_trade.open_order_id @@ -3626,7 +3632,7 @@ def test_execute_trade_exit_market_order( 'freqtrade.exchange.Exchange', fetch_ticker=ticker_usdt, get_fee=fee, - _is_dry_limit_order_filled=MagicMock(return_value=False), + _is_dry_limit_order_filled=MagicMock(return_value=True), ) patch_whitelist(mocker, default_conf_usdt) freqtrade = FreqtradeBot(default_conf_usdt) @@ -3642,7 +3648,8 @@ def test_execute_trade_exit_market_order( # Increase the price and sell it mocker.patch.multiple( 'freqtrade.exchange.Exchange', - fetch_ticker=ticker_usdt_sell_up + fetch_ticker=ticker_usdt_sell_up, + _is_dry_limit_order_filled=MagicMock(return_value=False), ) freqtrade.config['order_types']['exit'] = 'market' @@ -3655,7 +3662,7 @@ def test_execute_trade_exit_market_order( assert not trade.is_open assert trade.close_profit == profit_ratio - assert rpc_mock.call_count == 3 + assert rpc_mock.call_count == 4 last_msg = rpc_mock.call_args_list[-2][0][0] assert { 'type': RPCMessageType.EXIT, From b609dbcd8648937ed00785b0cab32faca1512859 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 19 Jul 2022 19:51:03 +0200 Subject: [PATCH 126/220] Update mdx_truly_sane_lists to be compatible with markdown again --- .gitignore | 2 ++ docs/requirements-docs.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 97f77f779..d6cec5225 100644 --- a/.gitignore +++ b/.gitignore @@ -80,6 +80,8 @@ instance/ # Sphinx documentation docs/_build/ +# Mkdocs documentation +site/ # PyBuilder target/ diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index a5fe8b921..a07f4f944 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,6 +1,6 @@ markdown==3.4.1 mkdocs==1.3.0 mkdocs-material==8.3.9 -mdx_truly_sane_lists==1.2 +mdx_truly_sane_lists==1.3 pymdown-extensions==9.5 jinja2==3.1.2 From ac2e8d760e2359ca5d26a8ce7dabf370873b0a6c Mon Sep 17 00:00:00 2001 From: rzrymiak <106121613+rzrymiak@users.noreply.github.com> Date: Tue, 19 Jul 2022 14:24:44 -0700 Subject: [PATCH 127/220] Added description heading to README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 881895c9a..828a3d1f9 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ [![Documentation](https://readthedocs.org/projects/freqtrade/badge/)](https://www.freqtrade.io) [![Maintainability](https://api.codeclimate.com/v1/badges/5737e6d668200b7518ff/maintainability)](https://codeclimate.com/github/freqtrade/freqtrade/maintainability) +## Description + Freqtrade is a free and open source crypto trading bot written in Python. It is designed to support all major exchanges and be controlled via Telegram or webUI. It contains backtesting, plotting and money management tools as well as strategy optimization by machine learning. ![freqtrade](https://raw.githubusercontent.com/freqtrade/freqtrade/develop/docs/assets/freqtrade-screenshot.png) @@ -193,7 +195,7 @@ Issues labeled [good first issue](https://github.com/freqtrade/freqtrade/labels/ The clock must be accurate, synchronized to a NTP server very frequently to avoid problems with communication to the exchanges. -### Min hardware required +### Minimum hardware required To run this bot we recommend you a cloud instance with a minimum of: From 32c3f62934f97520490be1b009a5d0f5dc7dab4f Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 22 Jul 2022 19:45:00 +0200 Subject: [PATCH 128/220] Fix documentation typo closes #7115 --- docs/stoploss.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/stoploss.md b/docs/stoploss.md index 6ddb485a4..249c40109 100644 --- a/docs/stoploss.md +++ b/docs/stoploss.md @@ -175,8 +175,8 @@ Before this, `stoploss` is used for the trailing stoploss. * assuming the asset now increases to 102$ * the stoploss will now be at 91.8$ - 10% below the highest observed rate * assuming the asset now increases to 103.5$ (above the offset configured) - * the stop loss will now be -2% of 103$ = 101.42$ - * now the asset drops in value to 102\$, the stop loss will still be 101.42$ and would trigger once price breaks below 101.42$ + * the stop loss will now be -2% of 103.5$ = 101.43$ + * now the asset drops in value to 102\$, the stop loss will still be 101.43$ and would trigger once price breaks below 101.43$ ### Trailing stop loss only once the trade has reached a certain offset From e97468964a46bc7464928a1626fa60f7b946ffbc Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Jul 2022 08:42:20 +0200 Subject: [PATCH 129/220] Add support for --timeframe-detail in hyperopt fix #7070 --- docs/hyperopt.md | 23 ++++++++++++++++------- freqtrade/commands/arguments.py | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index 55fe8f008..c9ec30056 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -40,13 +40,15 @@ pip install -r requirements-hyperopt.txt ``` usage: freqtrade hyperopt [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH] [--userdir PATH] [-s NAME] [--strategy-path PATH] - [-i TIMEFRAME] [--timerange TIMERANGE] + [--recursive-strategy-search] [-i TIMEFRAME] + [--timerange TIMERANGE] [--data-format-ohlcv {json,jsongz,hdf5}] [--max-open-trades INT] [--stake-amount STAKE_AMOUNT] [--fee FLOAT] [-p PAIRS [PAIRS ...]] [--hyperopt-path PATH] [--eps] [--dmmp] [--enable-protections] - [--dry-run-wallet DRY_RUN_WALLET] [-e INT] + [--dry-run-wallet DRY_RUN_WALLET] + [--timeframe-detail TIMEFRAME_DETAIL] [-e INT] [--spaces {all,buy,sell,roi,stoploss,trailing,protection,default} [{all,buy,sell,roi,stoploss,trailing,protection,default} ...]] [--print-all] [--no-color] [--print-json] [-j JOBS] [--random-state INT] [--min-trades INT] @@ -89,6 +91,9 @@ optional arguments: --dry-run-wallet DRY_RUN_WALLET, --starting-balance DRY_RUN_WALLET Starting balance, used for backtesting / hyperopt and dry-runs. + --timeframe-detail TIMEFRAME_DETAIL + Specify detail timeframe for backtesting (`1m`, `5m`, + `30m`, `1h`, `1d`). -e INT, --epochs INT Specify number of epochs (default: 100). --spaces {all,buy,sell,roi,stoploss,trailing,protection,default} [{all,buy,sell,roi,stoploss,trailing,protection,default} ...] Specify which parameters to hyperopt. Space-separated @@ -146,7 +151,9 @@ Strategy arguments: Specify strategy class name which will be used by the bot. --strategy-path PATH Specify additional strategy lookup path. - + --recursive-strategy-search + Recursively search for a strategy in the strategies + folder. ``` ### Hyperopt checklist @@ -867,10 +874,12 @@ You can also enable position stacking in the configuration file by explicitly se As hyperopt consumes a lot of memory (the complete data needs to be in memory once per parallel backtesting process), it's likely that you run into "out of memory" errors. To combat these, you have multiple options: -* reduce the amount of pairs -* reduce the timerange used (`--timerange `) -* reduce the number of parallel processes (`-j `) -* Increase the memory of your machine +* Reduce the amount of pairs. +* Reduce the timerange used (`--timerange `). +* Avoid using `--timeframe-detail` (this loads a lot of additional data into memory). +* Reduce the number of parallel processes (`-j `). +* Increase the memory of your machine. + ## The objective has been evaluated at this point before. diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 1e3e2845a..fc3eda14d 100644 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -28,7 +28,7 @@ ARGS_BACKTEST = ARGS_COMMON_OPTIMIZE + ["position_stacking", "use_max_market_pos ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "hyperopt_path", "position_stacking", "use_max_market_positions", - "enable_protections", "dry_run_wallet", + "enable_protections", "dry_run_wallet", "timeframe_detail", "epochs", "spaces", "print_all", "print_colorized", "print_json", "hyperopt_jobs", "hyperopt_random_state", "hyperopt_min_trades", From 5c4f60f376452783674819a2b2e02e0e6ce8acad Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Jul 2022 09:11:22 +0200 Subject: [PATCH 130/220] Improve configuration table formatting and ordering --- docs/configuration.md | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 0f3069478..412571674 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -116,6 +116,9 @@ This is similar to using multiple `--config` parameters, but simpler in usage as The table below will list all configuration parameters available. Freqtrade can also load many options via command line (CLI) arguments (check out the commands `--help` output for details). + +### Configuration option prevalence + The prevalence for all Options is as follows: - CLI arguments override any other option @@ -123,6 +126,8 @@ The prevalence for all Options is as follows: - Configuration files are used in sequence (the last file wins) and override Strategy configurations. - Strategy configurations are only used if they are not set via configuration or command-line arguments. These options are marked with [Strategy Override](#parameters-in-the-strategy) in the below table. +### Parameters table + Mandatory parameters are marked as **Required**, which means that they are required to be set in one of the possible ways. | Parameter | Description | @@ -135,7 +140,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `amend_last_stake_amount` | Use reduced last stake amount if necessary. [More information below](#configuring-amount-per-trade).
*Defaults to `false`.*
**Datatype:** Boolean | `last_stake_amount_min_ratio` | Defines minimum stake amount that has to be left and executed. Applies only to the last stake amount when it's amended to a reduced value (i.e. if `amend_last_stake_amount` is set to `true`). [More information below](#configuring-amount-per-trade).
*Defaults to `0.5`.*
**Datatype:** Float (as ratio) | `amount_reserve_percent` | Reserve some amount in min pair stake amount. The bot will reserve `amount_reserve_percent` + stoploss value when calculating min pair stake amount in order to avoid possible trade refusals.
*Defaults to `0.05` (5%).*
**Datatype:** Positive Float as ratio. -| `timeframe` | The timeframe to use (e.g `1m`, `5m`, `15m`, `30m`, `1h` ...). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** String +| `timeframe` | The timeframe to use (e.g `1m`, `5m`, `15m`, `30m`, `1h` ...). Usually missing in configuration, and specified in the strategy. [Strategy Override](#parameters-in-the-strategy).
**Datatype:** String | `fiat_display_currency` | Fiat currency used to show your profits. [More information below](#what-values-can-be-used-for-fiat_display_currency).
**Datatype:** String | `dry_run` | **Required.** Define if the bot must be in Dry Run or production mode.
*Defaults to `true`.*
**Datatype:** Boolean | `dry_run_wallet` | Define the starting amount in stake currency for the simulated wallet used by the bot running in Dry Run mode.
*Defaults to `1000`.*
**Datatype:** Float @@ -148,13 +153,16 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `trailing_stop_positive_offset` | Offset on when to apply `trailing_stop_positive`. Percentage value which should be positive. More details in the [stoploss documentation](stoploss.md#trailing-stop-loss-only-once-the-trade-has-reached-a-certain-offset). [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0.0` (no offset).*
**Datatype:** Float | `trailing_only_offset_is_reached` | Only apply trailing stoploss when the offset is reached. [stoploss documentation](stoploss.md). [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean | `fee` | Fee used during backtesting / dry-runs. Should normally not be configured, which has freqtrade fall back to the exchange default fee. Set as ratio (e.g. 0.001 = 0.1%). Fee is applied twice for each trade, once when buying, once when selling.
**Datatype:** Float (as ratio) +| `futures_funding_rate` | User-specified funding rate to be used when historical funding rates are not available from the exchange. This does not overwrite real historical rates. It is recommended that this be set to 0 unless you are testing a specific coin and you understand how the funding rate will affect freqtrade's profit calculations. [More information here](leverage.md#unavailable-funding-rates)
*Defaults to None.*
**Datatype:** Float | `trading_mode` | Specifies if you want to trade regularly, trade with leverage, or trade contracts whose prices are derived from matching cryptocurrency prices. [leverage documentation](leverage.md).
*Defaults to `"spot"`.*
**Datatype:** String | `margin_mode` | When trading with leverage, this determines if the collateral owned by the trader will be shared or isolated to each trading pair [leverage documentation](leverage.md).
**Datatype:** String | `liquidation_buffer` | A ratio specifying how large of a safety net to place between the liquidation price and the stoploss to prevent a position from reaching the liquidation price [leverage documentation](leverage.md).
*Defaults to `0.05`.*
**Datatype:** Float +| | **Unfilled timeout** | `unfilledtimeout.entry` | **Required.** How long (in minutes or seconds) the bot will wait for an unfilled entry order to complete, after which the order will be cancelled and repeated at current (new) price, as long as there is a signal. [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Integer | `unfilledtimeout.exit` | **Required.** How long (in minutes or seconds) the bot will wait for an unfilled exit order to complete, after which the order will be cancelled and repeated at current (new) price, as long as there is a signal. [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Integer | `unfilledtimeout.unit` | Unit to use in unfilledtimeout setting. Note: If you set unfilledtimeout.unit to "seconds", "internals.process_throttle_secs" must be inferior or equal to timeout [Strategy Override](#parameters-in-the-strategy).
*Defaults to `minutes`.*
**Datatype:** String | `unfilledtimeout.exit_timeout_count` | How many times can exit orders time out. Once this number of timeouts is reached, an emergency exit is triggered. 0 to disable and allow unlimited order cancels. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0`.*
**Datatype:** Integer +| | **Pricing** | `entry_pricing.price_side` | Select the side of the spread the bot should look at to get the entry rate. [More information below](#buy-price-side).
*Defaults to `same`.*
**Datatype:** String (either `ask`, `bid`, `same` or `other`). | `entry_pricing.price_last_balance` | **Required.** Interpolate the bidding price. More information [below](#entry-price-without-orderbook-enabled). | `entry_pricing.use_order_book` | Enable entering using the rates in [Order Book Entry](#entry-price-with-orderbook-enabled).
*Defaults to `True`.*
**Datatype:** Boolean @@ -165,6 +173,8 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `exit_pricing.price_last_balance` | Interpolate the exiting price. More information [below](#exit-price-without-orderbook-enabled). | `exit_pricing.use_order_book` | Enable exiting of open trades using [Order Book Exit](#exit-price-with-orderbook-enabled).
*Defaults to `True`.*
**Datatype:** Boolean | `exit_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to exit. I.e. a value of 2 will allow the bot to pick the 2nd ask rate in [Order Book Exit](#exit-price-with-orderbook-enabled)
*Defaults to `1`.*
**Datatype:** Positive Integer +| `custom_price_max_distance_ratio` | Configure maximum distance ratio between current and custom entry or exit price.
*Defaults to `0.02` 2%).*
**Datatype:** Positive float +| | **TODO** | `use_exit_signal` | Use exit signals produced by the strategy in addition to the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `true`.*
**Datatype:** Boolean | `exit_profit_only` | Wait until the bot reaches `exit_profit_offset` before taking an exit decision. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean | `exit_profit_offset` | Exit-signal is only active above this value. Only active in combination with `exit_profit_only=True`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0.0`.*
**Datatype:** Float (as ratio) @@ -172,8 +182,9 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `ignore_buying_expired_candle_after` | Specifies the number of seconds until a buy signal is no longer used.
**Datatype:** Integer | `order_types` | Configure order-types depending on the action (`"entry"`, `"exit"`, `"stoploss"`, `"stoploss_on_exchange"`). [More information below](#understand-order_types). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict | `order_time_in_force` | Configure time in force for entry and exit orders. [More information below](#understand-order_time_in_force). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict -| `custom_price_max_distance_ratio` | Configure maximum distance ratio between current and custom entry or exit price.
*Defaults to `0.02` 2%).*
**Datatype:** Positive float -| `recursive_strategy_search` | Set to `true` to recursively search sub-directories inside `user_data/strategies` for a strategy.
**Datatype:** Boolean +| `position_adjustment_enable` | Enables the strategy to use position adjustments (additional buys or sells). [More information here](strategy-callbacks.md#adjust-trade-position).
[Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean +| `max_entry_position_adjustment` | Maximum additional order(s) for each open trade on top of the first entry Order. Set it to `-1` for unlimited additional orders. [More information here](strategy-callbacks.md#adjust-trade-position).
[Strategy Override](#parameters-in-the-strategy).
*Defaults to `-1`.*
**Datatype:** Positive Integer or -1 +| | **Exchange** | `exchange.name` | **Required.** Name of the exchange class to use. [List below](#user-content-what-values-for-exchangename).
**Datatype:** String | `exchange.sandbox` | Use the 'sandbox' version of the exchange, where the exchange provides a sandbox for risk-free integration. See [here](sandbox-testing.md) in more details.
**Datatype:** Boolean | `exchange.key` | API key to use for the exchange. Only required when you are in production mode.
**Keep it in secret, do not disclose publicly.**
**Datatype:** String @@ -190,14 +201,19 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `exchange.skip_open_order_update` | Skips open order updates on startup should the exchange cause problems. Only relevant in live conditions.
*Defaults to `false`
**Datatype:** Boolean | `exchange.unknown_fee_rate` | Fallback value to use when calculating trading fees. This can be useful for exchanges which have fees in non-tradable currencies. The value provided here will be multiplied with the "fee cost".
*Defaults to `None`
**Datatype:** float | `exchange.log_responses` | Log relevant exchange responses. For debug mode only - use with care.
*Defaults to `false`
**Datatype:** Boolean -| `edge.*` | Please refer to [edge configuration document](edge.md) for detailed explanation. | `experimental.block_bad_exchanges` | Block exchanges known to not work with freqtrade. Leave on default unless you want to test if that exchange works now.
*Defaults to `true`.*
**Datatype:** Boolean +| | **Plugins** +| `edge.*` | Please refer to [edge configuration document](edge.md) for detailed explanation of all possible configuration options. | `pairlists` | Define one or more pairlists to be used. [More information](plugins.md#pairlists-and-pairlist-handlers).
*Defaults to `StaticPairList`.*
**Datatype:** List of Dicts | `protections` | Define one or more protections to be used. [More information](plugins.md#protections).
**Datatype:** List of Dicts +| | **Telegram** | `telegram.enabled` | Enable the usage of Telegram.
**Datatype:** Boolean | `telegram.token` | Your Telegram bot token. Only required if `telegram.enabled` is `true`.
**Keep it in secret, do not disclose publicly.**
**Datatype:** String | `telegram.chat_id` | Your personal Telegram account id. Only required if `telegram.enabled` is `true`.
**Keep it in secret, do not disclose publicly.**
**Datatype:** String | `telegram.balance_dust_level` | Dust-level (in stake currency) - currencies with a balance below this will not be shown by `/balance`.
**Datatype:** float +| `telegram.reload` | Allow "reload" buttons on telegram messages.
*Defaults to `True`.
**Datatype:** boolean +| `telegram.notification_settings.*` | Detailed notification settings. Refer to the [telegram documentation](telegram-usage.md) for details.
**Datatype:** dictionary +| | **Webhook** | `webhook.enabled` | Enable usage of Webhook notifications
**Datatype:** Boolean | `webhook.url` | URL for the webhook. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String | `webhook.webhookentry` | Payload to send on entry. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String @@ -207,6 +223,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `webhook.webhookexitcancel` | Payload to send on exit order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String | `webhook.webhookexitfill` | Payload to send on exit order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String | `webhook.webhookstatus` | Payload to send on status calls. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String +| | **Rest API / FreqUI** | `api_server.enabled` | Enable usage of API Server. See the [API Server documentation](rest-api.md) for more details.
**Datatype:** Boolean | `api_server.listen_ip_address` | Bind IP address. See the [API Server documentation](rest-api.md) for more details.
**Datatype:** IPv4 | `api_server.listen_port` | Bind Port. See the [API Server documentation](rest-api.md) for more details.
**Datatype:** Integer between 1024 and 65535 @@ -214,23 +231,22 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `api_server.username` | Username for API server. See the [API Server documentation](rest-api.md) for more details.
**Keep it in secret, do not disclose publicly.**
**Datatype:** String | `api_server.password` | Password for API server. See the [API Server documentation](rest-api.md) for more details.
**Keep it in secret, do not disclose publicly.**
**Datatype:** String | `bot_name` | Name of the bot. Passed via API to a client - can be shown to distinguish / name bots.
*Defaults to `freqtrade`*
**Datatype:** String -| `db_url` | Declares database URL to use. NOTE: This defaults to `sqlite:///tradesv3.dryrun.sqlite` if `dry_run` is `true`, and to `sqlite:///tradesv3.sqlite` for production instances.
**Datatype:** String, SQLAlchemy connect string +| | **Other** | `initial_state` | Defines the initial application state. If set to stopped, then the bot has to be explicitly started via `/start` RPC command.
*Defaults to `stopped`.*
**Datatype:** Enum, either `stopped` or `running` | `force_entry_enable` | Enables the RPC Commands to force a Trade entry. More information below.
**Datatype:** Boolean | `disable_dataframe_checks` | Disable checking the OHLCV dataframe returned from the strategy methods for correctness. Only use when intentionally changing the dataframe and understand what you are doing. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `False`*.
**Datatype:** Boolean -| `strategy` | **Required** Defines Strategy class to use. Recommended to be set via `--strategy NAME`.
**Datatype:** ClassName -| `strategy_path` | Adds an additional strategy lookup path (must be a directory).
**Datatype:** String | `internals.process_throttle_secs` | Set the process throttle, or minimum loop duration for one bot iteration loop. Value in second.
*Defaults to `5` seconds.*
**Datatype:** Positive Integer | `internals.heartbeat_interval` | Print heartbeat message every N seconds. Set to 0 to disable heartbeat messages.
*Defaults to `60` seconds.*
**Datatype:** Positive Integer or 0 | `internals.sd_notify` | Enables use of the sd_notify protocol to tell systemd service manager about changes in the bot state and issue keep-alive pings. See [here](installation.md#7-optional-configure-freqtrade-as-a-systemd-service) for more details.
**Datatype:** Boolean -| `logfile` | Specifies logfile name. Uses a rolling strategy for log file rotation for 10 files with the 1MB limit per file.
**Datatype:** String +| `strategy` | **Required** Defines Strategy class to use. Recommended to be set via `--strategy NAME`.
**Datatype:** ClassName +| `strategy_path` | Adds an additional strategy lookup path (must be a directory).
**Datatype:** String +| `recursive_strategy_search` | Set to `true` to recursively search sub-directories inside `user_data/strategies` for a strategy.
**Datatype:** Boolean | `user_data_dir` | Directory containing user data.
*Defaults to `./user_data/`*.
**Datatype:** String +| `db_url` | Declares database URL to use. NOTE: This defaults to `sqlite:///tradesv3.dryrun.sqlite` if `dry_run` is `true`, and to `sqlite:///tradesv3.sqlite` for production instances.
**Datatype:** String, SQLAlchemy connect string +| `logfile` | Specifies logfile name. Uses a rolling strategy for log file rotation for 10 files with the 1MB limit per file.
**Datatype:** String | `add_config_files` | Additional config files. These files will be loaded and merged with the current config file. The files are resolved relative to the initial file.
*Defaults to `[]`*.
**Datatype:** List of strings | `dataformat_ohlcv` | Data format to use to store historical candle (OHLCV) data.
*Defaults to `json`*.
**Datatype:** String | `dataformat_trades` | Data format to use to store historical trades data.
*Defaults to `jsongz`*.
**Datatype:** String -| `position_adjustment_enable` | Enables the strategy to use position adjustments (additional buys or sells). [More information here](strategy-callbacks.md#adjust-trade-position).
[Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean -| `max_entry_position_adjustment` | Maximum additional order(s) for each open trade on top of the first entry Order. Set it to `-1` for unlimited additional orders. [More information here](strategy-callbacks.md#adjust-trade-position).
[Strategy Override](#parameters-in-the-strategy).
*Defaults to `-1`.*
**Datatype:** Positive Integer or -1 -| `futures_funding_rate` | User-specified funding rate to be used when historical funding rates are not available from the exchange. This does not overwrite real historical rates. It is recommended that this be set to 0 unless you are testing a specific coin and you understand how the funding rate will affect freqtrade's profit calculations. [More information here](leverage.md#unavailable-funding-rates)
*Defaults to None.*
**Datatype:** Float ### Parameters in the strategy From a02d02ac1251a1525545ee5fa3ba87fb61ac5899 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Jul 2022 14:43:52 +0200 Subject: [PATCH 131/220] Enhance protections tests to have orders in mock trade --- tests/plugins/test_protections.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/plugins/test_protections.py b/tests/plugins/test_protections.py index 172e1f077..3c333200c 100644 --- a/tests/plugins/test_protections.py +++ b/tests/plugins/test_protections.py @@ -6,6 +6,7 @@ import pytest from freqtrade import constants from freqtrade.enums import ExitType from freqtrade.persistence import PairLocks, Trade +from freqtrade.persistence.trade_model import Order from freqtrade.plugins.protectionmanager import ProtectionManager from tests.conftest import get_patched_freqtradebot, log_has_re @@ -30,7 +31,37 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool, amount=0.01 / open_rate, exchange='binance', is_short=is_short, + leverage=1, ) + + trade.orders.append(Order( + ft_order_side=trade.entry_side, + order_id=f'{pair}-{trade.entry_side}-{trade.open_date}', + ft_pair=pair, + amount=trade.amount, + filled=trade.amount, + remaining=0, + price=open_rate, + average=open_rate, + status="closed", + order_type="market", + side=trade.entry_side, + )) + if not is_open: + trade.orders.append(Order( + ft_order_side=trade.exit_side, + order_id=f'{pair}-{trade.exit_side}-{trade.close_date}', + ft_pair=pair, + amount=trade.amount, + filled=trade.amount, + remaining=0, + price=open_rate * (2 - profit_rate if is_short else profit_rate), + average=open_rate * (2 - profit_rate if is_short else profit_rate), + status="closed", + order_type="market", + side=trade.exit_side, + )) + trade.recalc_open_trade_value() if not is_open: trade.close(open_rate * (2 - profit_rate if is_short else profit_rate)) From 80845807e113527fcbf2f716db62a4beb2ddae89 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Jul 2022 15:14:38 +0200 Subject: [PATCH 132/220] Improve some test resiliance --- tests/test_freqtradebot.py | 14 ++++++++------ tests/test_persistence.py | 8 ++++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index e431e7ac3..a4b10fbcd 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -2139,8 +2139,6 @@ def test_handle_trade( assert trade time.sleep(0.01) # Race condition fix - oobj = Order.parse_from_ccxt_object(enter_order, enter_order['symbol'], entry_side(is_short)) - trade.update_trade(oobj) assert trade.is_open is True freqtrade.wallets.update() @@ -2150,11 +2148,15 @@ def test_handle_trade( assert trade.open_order_id == exit_order['id'] # Simulate fulfilled LIMIT_SELL order for trade - oobj = Order.parse_from_ccxt_object(exit_order, exit_order['symbol'], exit_side(is_short)) - trade.update_trade(oobj) + trade.orders[-1].ft_is_open = False + trade.orders[-1].status = 'closed' + trade.orders[-1].filled = trade.orders[-1].remaining + trade.orders[-1].remaining = 0.0 - assert trade.close_rate == 2.0 if is_short else 2.2 - assert trade.close_profit == close_profit + trade.update_trade(trade.orders[-1]) + + assert trade.close_rate == (2.0 if is_short else 2.2) + assert pytest.approx(trade.close_profit) == close_profit assert trade.calc_profit(trade.close_rate) == 5.685 assert trade.close_date is not None assert trade.exit_reason == 'sell_signal1' diff --git a/tests/test_persistence.py b/tests/test_persistence.py index a09711048..529f6dc31 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -481,6 +481,7 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_ trade.open_order_id = 'something' oobj = Order.parse_from_ccxt_object(enter_order, 'ADA/USDT', entry_side) + trade.orders.append(oobj) trade.update_trade(oobj) assert trade.open_order_id is None assert trade.open_rate == open_rate @@ -496,11 +497,12 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_ trade.open_order_id = 'something' time_machine.move_to("2022-03-31 21:45:05 +00:00") oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', exit_side) + trade.orders.append(oobj) trade.update_trade(oobj) assert trade.open_order_id is None assert trade.close_rate == close_rate - assert trade.close_profit == profit + assert pytest.approx(trade.close_profit) == profit assert trade.close_date is not None assert log_has_re(f"LIMIT_{exit_side.upper()} has been fulfilled for " r"Trade\(id=2, pair=ADA/USDT, amount=30.00000000, " @@ -529,6 +531,7 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee, trade.open_order_id = 'something' oobj = Order.parse_from_ccxt_object(market_buy_order_usdt, 'ADA/USDT', 'buy') + trade.orders.append(oobj) trade.update_trade(oobj) assert trade.open_order_id is None assert trade.open_rate == 2.0 @@ -543,10 +546,11 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee, trade.is_open = True trade.open_order_id = 'something' oobj = Order.parse_from_ccxt_object(market_sell_order_usdt, 'ADA/USDT', 'sell') + trade.orders.append(oobj) trade.update_trade(oobj) assert trade.open_order_id is None assert trade.close_rate == 2.2 - assert trade.close_profit == round(0.0945137157107232, 8) + assert pytest.approx(trade.close_profit) == 0.094513715710723 assert trade.close_date is not None assert log_has_re(r"MARKET_SELL has been fulfilled for Trade\(id=1, " r"pair=ADA/USDT, amount=30.00000000, is_short=False, leverage=1.0, " From 24a786bedd7e83a9e68e99041f6dd4d89fd018fc Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Jul 2022 15:23:24 +0200 Subject: [PATCH 133/220] Update rpc test to contain sell order --- tests/rpc/test_rpc_telegram.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 91ee92fd7..f69b7e878 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -686,6 +686,7 @@ def test_profit_handle(default_conf_usdt, update, ticker_usdt, ticker_sell_up, f # Simulate fulfilled LIMIT_SELL order for trade oobj = Order.parse_from_ccxt_object( limit_sell_order_usdt, limit_sell_order_usdt['symbol'], 'sell') + trade.orders.append(oobj) trade.update_trade(oobj) trade.close_date = datetime.now(timezone.utc) @@ -707,7 +708,7 @@ def test_profit_handle(default_conf_usdt, update, ticker_usdt, ticker_sell_up, f assert '*Best Performing:* `ETH/USDT: 9.45%`' in msg_mock.call_args_list[-1][0][0] assert '*Max Drawdown:*' in msg_mock.call_args_list[-1][0][0] assert '*Profit factor:*' in msg_mock.call_args_list[-1][0][0] - assert '*Trading volume:* `60 USDT`' in msg_mock.call_args_list[-1][0][0] + assert '*Trading volume:* `126 USDT`' in msg_mock.call_args_list[-1][0][0] @pytest.mark.parametrize('is_short', [True, False]) From 7682c9ace70d6a6ad1e6a5f0c283d8dad067790c Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Jul 2022 15:27:52 +0200 Subject: [PATCH 134/220] Update trade_close test to include orders --- tests/test_persistence.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 529f6dc31..838c4c22a 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -628,14 +628,41 @@ def test_trade_close(limit_buy_order_usdt, limit_sell_order_usdt, fee): open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=10), interest_rate=0.0005, exchange='binance', - trading_mode=margin + trading_mode=margin, + leverage=1.0, ) + trade.orders.append(Order( + ft_order_side=trade.entry_side, + order_id=f'{trade.pair}-{trade.entry_side}-{trade.open_date}', + ft_pair=trade.pair, + amount=trade.amount, + filled=trade.amount, + remaining=0, + price=trade.open_rate, + average=trade.open_rate, + status="closed", + order_type="limit", + side=trade.entry_side, + )) + trade.orders.append(Order( + ft_order_side=trade.exit_side, + order_id=f'{trade.pair}-{trade.exit_side}-{trade.open_date}', + ft_pair=trade.pair, + amount=trade.amount, + filled=trade.amount, + remaining=0, + price=2.2, + average=2.2, + status="closed", + order_type="limit", + side=trade.exit_side, + )) assert trade.close_profit is None assert trade.close_date is None assert trade.is_open is True trade.close(2.2) assert trade.is_open is False - assert trade.close_profit == round(0.0945137157107232, 8) + assert pytest.approx(trade.close_profit) == 0.094513715 assert trade.close_date is not None new_date = arrow.Arrow(2020, 2, 2, 15, 6, 1).datetime, From 2eb1d18c2a8f788fa47826ae8fca45795bcba56d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Jul 2022 19:56:38 +0200 Subject: [PATCH 135/220] Don't load leverage tiers when not necessary --- freqtrade/exchange/exchange.py | 5 +++-- freqtrade/freqtradebot.py | 3 ++- freqtrade/optimize/backtesting.py | 3 ++- freqtrade/resolvers/exchange_resolver.py | 13 +++++++++---- freqtrade/rpc/api_server/deps.py | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index a430cdac5..11e37b953 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -88,7 +88,8 @@ class Exchange: # TradingMode.SPOT always supported and not required in this list ] - def __init__(self, config: Dict[str, Any], validate: bool = True) -> None: + def __init__(self, config: Dict[str, Any], validate: bool = True, + load_leverage_tiers: bool = False) -> None: """ Initializes this module with the given config, it does basic validation whether the specified exchange and pairs are valid. @@ -186,7 +187,7 @@ class Exchange: self.markets_refresh_interval: int = exchange_config.get( "markets_refresh_interval", 60) * 60 - if self.trading_mode != TradingMode.SPOT: + if self.trading_mode != TradingMode.SPOT and load_leverage_tiers: self.fill_leverage_tiers() self.additional_exchange_init() diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 2007f9b4e..43608cae7 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -65,7 +65,8 @@ class FreqtradeBot(LoggingMixin): # Check config consistency here since strategies can set certain options validate_config_consistency(config) - self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config) + self.exchange = ExchangeResolver.load_exchange( + self.config['exchange']['name'], self.config, load_leverage_tiers=True) init_db(self.config['db_url']) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index da28a8d93..4d16dc0f1 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -84,7 +84,8 @@ class Backtesting: self.processed_dfs: Dict[str, Dict] = {} self._exchange_name = self.config['exchange']['name'] - self.exchange = ExchangeResolver.load_exchange(self._exchange_name, self.config) + self.exchange = ExchangeResolver.load_exchange( + self._exchange_name, self.config, load_leverage_tiers=True) self.dataprovider = DataProvider(self.config, self.exchange) if self.config.get('strategy_list'): diff --git a/freqtrade/resolvers/exchange_resolver.py b/freqtrade/resolvers/exchange_resolver.py index 4dfbf445b..a2f572ff2 100644 --- a/freqtrade/resolvers/exchange_resolver.py +++ b/freqtrade/resolvers/exchange_resolver.py @@ -18,7 +18,8 @@ class ExchangeResolver(IResolver): object_type = Exchange @staticmethod - def load_exchange(exchange_name: str, config: dict, validate: bool = True) -> Exchange: + def load_exchange(exchange_name: str, config: dict, validate: bool = True, + load_leverage_tiers: bool = False) -> Exchange: """ Load the custom class from config parameter :param exchange_name: name of the Exchange to load @@ -29,9 +30,13 @@ class ExchangeResolver(IResolver): exchange_name = exchange_name.title() exchange = None try: - exchange = ExchangeResolver._load_exchange(exchange_name, - kwargs={'config': config, - 'validate': validate}) + exchange = ExchangeResolver._load_exchange( + exchange_name, + kwargs={ + 'config': config, + 'validate': validate, + 'load_leverage_tiers': load_leverage_tiers} + ) except ImportError: logger.info( f"No {exchange_name} specific subclass found. Using the generic class instead.") diff --git a/freqtrade/rpc/api_server/deps.py b/freqtrade/rpc/api_server/deps.py index f5e61602e..81c013efa 100644 --- a/freqtrade/rpc/api_server/deps.py +++ b/freqtrade/rpc/api_server/deps.py @@ -37,7 +37,7 @@ def get_exchange(config=Depends(get_config)): if not ApiServer._exchange: from freqtrade.resolvers import ExchangeResolver ApiServer._exchange = ExchangeResolver.load_exchange( - config['exchange']['name'], config) + config['exchange']['name'], config, load_leverage_tiers=False) return ApiServer._exchange From 6e691a016d1ae3fcd18596d45ab48d24fecf4d35 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 24 Jul 2022 10:24:59 +0200 Subject: [PATCH 136/220] Use leverage-tiers loading in tests --- tests/conftest.py | 2 +- tests/exchange/test_ccxt_compat.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 3158e9ede..237c3fcc0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -148,7 +148,7 @@ def get_patched_exchange(mocker, config, api_mock=None, id='binance', patch_exchange(mocker, api_mock, id, mock_markets, mock_supported_modes) config['exchange']['name'] = id try: - exchange = ExchangeResolver.load_exchange(id, config) + exchange = ExchangeResolver.load_exchange(id, config, load_leverage_tiers=True) except ImportError: exchange = Exchange(config) return exchange diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 74106f28b..7bb52ccaf 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -137,7 +137,8 @@ def exchange_futures(request, exchange_conf, class_mocker): 'freqtrade.exchange.binance.Binance.fill_leverage_tiers') class_mocker.patch('freqtrade.exchange.exchange.Exchange.fetch_trading_fees') class_mocker.patch('freqtrade.exchange.okx.Okx.additional_exchange_init') - exchange = ExchangeResolver.load_exchange(request.param, exchange_conf, validate=True) + exchange = ExchangeResolver.load_exchange( + request.param, exchange_conf, validate=True, load_leverage_tiers=True) yield exchange, request.param From 83cac7bee2e6d94e47db336e1b83f2d55873c3d9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 24 Jul 2022 10:51:13 +0200 Subject: [PATCH 137/220] Improve some more tests by adding proper orders --- tests/conftest.py | 19 ++++++++++++++++++- tests/rpc/test_rpc.py | 2 ++ tests/test_freqtradebot.py | 24 +++++++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 237c3fcc0..ff3e1007f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2609,7 +2609,7 @@ def open_trade_usdt(): pair='ADA/USDT', open_rate=2.0, exchange='binance', - open_order_id='123456789', + open_order_id='123456789_exit', amount=30.0, fee_open=0.0, fee_close=0.0, @@ -2634,6 +2634,23 @@ def open_trade_usdt(): cost=trade.open_rate * trade.amount, order_date=trade.open_date, order_filled_date=trade.open_date, + ), + Order( + ft_order_side='exit', + ft_pair=trade.pair, + ft_is_open=True, + order_id='123456789_exit', + status="open", + symbol=trade.pair, + order_type="limit", + side="sell", + price=trade.open_rate, + average=trade.open_rate, + filled=trade.amount, + remaining=0, + cost=trade.open_rate * trade.amount, + order_date=trade.open_date, + order_filled_date=trade.open_date, ) ] return trade diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index d20646e60..6e19fcaf3 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -830,6 +830,8 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: assert cancel_order_mock.call_count == 2 assert trade.amount == amount + trade = Trade.query.filter(Trade.id == '3').first() + # make an limit-sell open trade mocker.patch( 'freqtrade.exchange.Exchange.fetch_order', diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index a4b10fbcd..66cbd7d9b 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -2759,6 +2759,8 @@ def test_check_handle_cancelled_exit( cancel_order_mock = MagicMock() limit_sell_order_old.update({"status": "canceled", 'filled': 0.0}) limit_sell_order_old['side'] = 'buy' if is_short else 'sell' + limit_sell_order_old['id'] = open_trade_usdt.open_order_id + patch_exchange(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -3098,7 +3100,27 @@ def test_handle_cancel_exit_limit(mocker, default_conf_usdt, fee) -> None: close_date=arrow.utcnow().datetime, exit_reason="sell_reason_whatever", ) - order = {'remaining': 1, + trade.orders = [ + Order( + ft_order_side='buy', + ft_pair=trade.pair, + ft_is_open=True, + order_id='123456', + status="closed", + symbol=trade.pair, + order_type="market", + side="buy", + price=trade.open_rate, + average=trade.open_rate, + filled=trade.amount, + remaining=0, + cost=trade.open_rate * trade.amount, + order_date=trade.open_date, + order_filled_date=trade.open_date, + ), + ] + order = {'id': "123456", + 'remaining': 1, 'amount': 1, 'status': "open"} reason = CANCEL_REASON['TIMEOUT'] From 1b49e45222547e701b8b90a6cc6d2f905c6c8853 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jul 2022 03:01:32 +0000 Subject: [PATCH 138/220] Bump orjson from 3.7.7 to 3.7.8 Bumps [orjson](https://github.com/ijl/orjson) from 3.7.7 to 3.7.8. - [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.7.7...3.7.8) --- 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 b27c8f559..a41c50f84 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,7 +28,7 @@ py_find_1st==1.1.5 # Load ticker files 30% faster python-rapidjson==1.8 # Properly format api responses -orjson==3.7.7 +orjson==3.7.8 # Notify systemd sdnotify==0.3.2 From d5933fb2affac545a7b462cb50f4479fd964d55b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jul 2022 03:01:37 +0000 Subject: [PATCH 139/220] Bump mkdocs from 1.3.0 to 1.3.1 Bumps [mkdocs](https://github.com/mkdocs/mkdocs) from 1.3.0 to 1.3.1. - [Release notes](https://github.com/mkdocs/mkdocs/releases) - [Commits](https://github.com/mkdocs/mkdocs/compare/1.3.0...1.3.1) --- updated-dependencies: - dependency-name: mkdocs 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 a07f4f944..ea09b853b 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,5 @@ markdown==3.4.1 -mkdocs==1.3.0 +mkdocs==1.3.1 mkdocs-material==8.3.9 mdx_truly_sane_lists==1.3 pymdown-extensions==9.5 From 98d0ad76bf1ed599ea3e3abd7da15a11c8c3caec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jul 2022 03:01:44 +0000 Subject: [PATCH 140/220] Bump types-requests from 2.28.1 to 2.28.3 Bumps [types-requests](https://github.com/python/typeshed) from 2.28.1 to 2.28.3. - [Release notes](https://github.com/python/typeshed/releases) - [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 3d91f29fd..fa56f1df9 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,6 +24,6 @@ nbconvert==6.5.0 # mypy types types-cachetools==5.2.1 types-filelock==3.2.7 -types-requests==2.28.1 +types-requests==2.28.3 types-tabulate==0.8.11 types-python-dateutil==2.8.18 From f93a3a5fca28b3c1677af181cfe7e4fa0443483c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jul 2022 03:01:52 +0000 Subject: [PATCH 141/220] Bump ccxt from 1.90.89 to 1.91.22 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.90.89 to 1.91.22. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.90.89...1.91.22) --- updated-dependencies: - dependency-name: ccxt 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 b27c8f559..4e1c477cb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.90.89 +ccxt==1.91.22 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.4 aiohttp==3.8.1 From 3ce46ff09e980570c72ede2b2359fc8c92db4996 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Jul 2022 07:19:21 +0200 Subject: [PATCH 142/220] Bump types-requests in pre-commit --- .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 a23181c37..cbdeef780 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: additional_dependencies: - types-cachetools==5.2.1 - types-filelock==3.2.7 - - types-requests==2.28.1 + - types-requests==2.28.3 - types-tabulate==0.8.11 - types-python-dateutil==2.8.18 # stages: [push] From 43343d0e55391fde8c0a469e23b387a346a37e38 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Jul 2022 07:21:12 +0200 Subject: [PATCH 143/220] Revert markdown to 3.3.7 --- 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 ea09b853b..205516d6d 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,4 +1,4 @@ -markdown==3.4.1 +markdown==3.3.7 mkdocs==1.3.1 mkdocs-material==8.3.9 mdx_truly_sane_lists==1.3 From 93340f546b2395d4e50bb51391299496a7620f4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jul 2022 05:53:10 +0000 Subject: [PATCH 144/220] Bump mypy from 0.961 to 0.971 Bumps [mypy](https://github.com/python/mypy) from 0.961 to 0.971. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.961...v0.971) --- updated-dependencies: - dependency-name: mypy 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 fa56f1df9..41e4722aa 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -7,7 +7,7 @@ coveralls==3.3.1 flake8==4.0.1 flake8-tidy-imports==4.8.0 -mypy==0.961 +mypy==0.971 pre-commit==2.20.0 pytest==7.1.2 pytest-asyncio==0.19.0 From 40969f20bfbfe2c84821a4553dc9c6963ca91415 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jul 2022 05:53:15 +0000 Subject: [PATCH 145/220] Bump types-python-dateutil from 2.8.18 to 2.8.19 Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.18 to 2.8.19. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-python-dateutil 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 fa56f1df9..425937d6e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -26,4 +26,4 @@ types-cachetools==5.2.1 types-filelock==3.2.7 types-requests==2.28.3 types-tabulate==0.8.11 -types-python-dateutil==2.8.18 +types-python-dateutil==2.8.19 From 47b52d4bab6d0d378759eabc72df94f424cfacd6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Jul 2022 07:58:16 +0200 Subject: [PATCH 146/220] Bump types-dateutil in pre-commit --- .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 cbdeef780..759ac0a6a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - types-filelock==3.2.7 - types-requests==2.28.3 - types-tabulate==0.8.11 - - types-python-dateutil==2.8.18 + - types-python-dateutil==2.8.19 # stages: [push] - repo: https://github.com/pycqa/isort From ea112fb58399a0d00ca0582d462fe3c639d33a7b Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Jul 2022 17:47:28 +0200 Subject: [PATCH 147/220] Add test for empty order (cancelled order) --- tests/exchange/test_exchange.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index ff8b4b40c..9252040ea 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -2910,6 +2910,9 @@ def test_check_order_canceled_empty(mocker, default_conf, exchange_name, order, ({'amount': 10.0, 'fee': {}}, False), ({'result': 'testest123'}, False), ('hello_world', False), + ({'status': 'canceled', 'amount': None, 'fee': None}, False), + ({'status': 'canceled', 'filled': None, 'amount': None, 'fee': None}, False), + ]) def test_is_cancel_order_result_suitable(mocker, default_conf, exchange_name, order, result): exchange = get_patched_exchange(mocker, default_conf, id=exchange_name) From 4c68bec171c2849afbb5363d9e9bd48d178de854 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Jul 2022 17:47:52 +0200 Subject: [PATCH 148/220] Fix problem in `is_cancel_order_result_suitable` fixes #7119 --- freqtrade/exchange/exchange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 11e37b953..79bc769e6 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1264,7 +1264,7 @@ class Exchange: return False required = ('fee', 'status', 'amount') - return all(k in corder for k in required) + return all(corder.get(k, None) is not None for k in required) def cancel_order_with_result(self, order_id: str, pair: str, amount: float) -> Dict: """ From a0b9388757e00ab04e29e87d265867009ccf6415 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 26 Jul 2022 17:57:25 +0200 Subject: [PATCH 149/220] Bump ccxt to 1.91.29 closes #7132 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 411827b62..b9e87749d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.91.22 +ccxt==1.91.29 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.4 aiohttp==3.8.1 From 229e8864bbeb33bbd0b4c3bc525131939e276ad2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 26 Jul 2022 20:15:49 +0200 Subject: [PATCH 150/220] Add send_msg capability to dataprovider --- freqtrade/data/dataprovider.py | 21 +++++++++++++++++++++ freqtrade/enums/rpcmessagetype.py | 2 ++ freqtrade/freqtradebot.py | 1 + freqtrade/rpc/rpc_manager.py | 12 ++++++++++++ freqtrade/rpc/telegram.py | 3 ++- 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index b9b118c00..800254533 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -5,12 +5,14 @@ including ticker and orderbook data, live and historical candle (OHLCV) data Common Interface for bot and strategy to access data. """ import logging +from collections import deque from datetime import datetime, timezone from typing import Any, Dict, List, Optional, Tuple from pandas import DataFrame from freqtrade.configuration import TimeRange +from freqtrade.configuration.PeriodicCache import PeriodicCache from freqtrade.constants import ListPairsWithTimeframes, PairWithTimeframe from freqtrade.data.history import load_pair_history from freqtrade.enums import CandleType, RunMode @@ -33,6 +35,9 @@ class DataProvider: self.__cached_pairs: Dict[PairWithTimeframe, Tuple[DataFrame, datetime]] = {} self.__slice_index: Optional[int] = None self.__cached_pairs_backtesting: Dict[PairWithTimeframe, DataFrame] = {} + self._msg_queue: deque = deque() + self.__msg_cache = PeriodicCache( + maxsize=1000, ttl=timeframe_to_seconds(self._config['timeframe'])) def _set_dataframe_max_index(self, limit_index: int): """ @@ -265,3 +270,19 @@ class DataProvider: if self._exchange is None: raise OperationalException(NO_EXCHANGE_EXCEPTION) return self._exchange.fetch_l2_order_book(pair, maximum) + + def send_msg(self, message: str, always_send: bool = False) -> None: + """ + TODO: Document me + :param message: Message to be sent. Must be below 4096. + :param always_send: If False, will send the message only once per candle, and surpress + identical messages. + Careful as this can end up spaming your chat. + Defaults to False + """ + if self.runmode not in (RunMode.DRY_RUN, RunMode.LIVE): + return + + if always_send or message not in self.__msg_cache: + self._msg_queue.append(message) + self.__msg_cache[message] = True diff --git a/freqtrade/enums/rpcmessagetype.py b/freqtrade/enums/rpcmessagetype.py index 584a011c2..415d8f18c 100644 --- a/freqtrade/enums/rpcmessagetype.py +++ b/freqtrade/enums/rpcmessagetype.py @@ -17,6 +17,8 @@ class RPCMessageType(Enum): PROTECTION_TRIGGER = 'protection_trigger' PROTECTION_TRIGGER_GLOBAL = 'protection_trigger_global' + STRATEGY_MSG = 'strategy_msg' + def __repr__(self): return self.value diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 43608cae7..9ea195c45 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -214,6 +214,7 @@ class FreqtradeBot(LoggingMixin): if self.trading_mode == TradingMode.FUTURES: self._schedule.run_pending() Trade.commit() + self.rpc.process_msg_queue(self.dataprovider._msg_queue) self.last_process = datetime.now(timezone.utc) def process_stopped(self) -> None: diff --git a/freqtrade/rpc/rpc_manager.py b/freqtrade/rpc/rpc_manager.py index 66e84029f..3ccf23228 100644 --- a/freqtrade/rpc/rpc_manager.py +++ b/freqtrade/rpc/rpc_manager.py @@ -2,6 +2,7 @@ This module contains class to manage RPC communications (Telegram, API, ...) """ import logging +from collections import deque from typing import Any, Dict, List from freqtrade.enums import RPCMessageType @@ -77,6 +78,17 @@ class RPCManager: except NotImplementedError: logger.error(f"Message type '{msg['type']}' not implemented by handler {mod.name}.") + def process_msg_queue(self, queue: deque) -> None: + """ + Process all messages in the queue. + """ + while queue: + msg = queue.popleft() + self.send_msg({ + 'type': RPCMessageType.STRATEGY_MSG, + 'msg': msg, + }) + def startup_messages(self, config: Dict[str, Any], pairlist, protections) -> None: if config['dry_run']: self.send_msg({ diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 2aff1d210..121324d90 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -376,7 +376,8 @@ class Telegram(RPCHandler): elif msg_type == RPCMessageType.STARTUP: message = f"{msg['status']}" - + elif msg_type == RPCMessageType.STRATEGY_MSG: + message = f"{msg['msg']}" else: raise NotImplementedError(f"Unknown message type: {msg_type}") return message From 7bac0546681e770d3156db987620a666e4e1a489 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 26 Jul 2022 20:24:52 +0200 Subject: [PATCH 151/220] Add documentation and clarity for send_msg --- docs/strategy-customization.md | 17 +++++++++++++++++ docs/telegram-usage.md | 4 +++- freqtrade/constants.py | 4 ++++ freqtrade/data/dataprovider.py | 8 +++++--- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/docs/strategy-customization.md b/docs/strategy-customization.md index 6947380dd..38d34d51b 100644 --- a/docs/strategy-customization.md +++ b/docs/strategy-customization.md @@ -731,6 +731,23 @@ if self.dp: !!! Warning "Warning about backtesting" This method will always return up-to-date values - so usage during backtesting / hyperopt will lead to wrong results. +### Send Notification + +The dataprovider `.send_msg()` function allows you to send custom notifications from your strategy. +Identical notifications will only be sent once per candle, unless the 2nd argument (`always_send`) is set to True. + +``` python + self.dp.send_msg(f"{metadata['pair']} just got hot!") + + # Force send this notification, avoid caching (Please read warning below!) + self.dp.send_msg(f"{metadata['pair']} just got hot!", always_send=True) +``` + +Notifications will only be sent in trading modes (Live/Dry-run) - so this method can be called without conditions for backtesting. + +!!! Warning "Spamming" + You can spam yourself pretty good by setting `always_send=True` in this method. Use this with great care and only in conditions you know will not happen throughout a candle to avoid a message every 5 seconds. + ### Complete Data-provider sample ```python diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index 9853e15c6..a690e18b9 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -98,6 +98,7 @@ Example configuration showing the different settings: "exit_fill": "off", "protection_trigger": "off", "protection_trigger_global": "on", + "strategy_msg": "off", "show_candle": "off" }, "reload": true, @@ -109,7 +110,8 @@ Example configuration showing the different settings: `exit` notifications are sent when the order is placed, while `exit_fill` notifications are sent when the order is filled on the exchange. `*_fill` notifications are off by default and must be explicitly enabled. `protection_trigger` notifications are sent when a protection triggers and `protection_trigger_global` notifications trigger when global protections are triggered. -`show_candle` - show candle values as part of entry/exit messages. Only possible value is "ohlc". +`strategy_msg` - Receive notifications from the strategy, sent via `self.dp.send_msg()` from the strategy [more details](strategy-customization.md#send-notification). +`show_candle` - show candle values as part of entry/exit messages. Only possible values are `"ohlc"` or `"off"`. `balance_dust_level` will define what the `/balance` command takes as "dust" - Currencies with a balance below this will be shown. `reload` allows you to disable reload-buttons on selected messages. diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 6d74ceafd..1d83d21a0 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -317,6 +317,10 @@ CONF_SCHEMA = { 'type': 'string', 'enum': ['off', 'ohlc'], }, + 'strategy_msg': { + 'type': 'string', + 'enum': TELEGRAM_SETTING_OPTIONS, + }, } }, 'reload': {'type': 'boolean'}, diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index 800254533..e21f10193 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -36,8 +36,9 @@ class DataProvider: self.__slice_index: Optional[int] = None self.__cached_pairs_backtesting: Dict[PairWithTimeframe, DataFrame] = {} self._msg_queue: deque = deque() + self.__msg_cache = PeriodicCache( - maxsize=1000, ttl=timeframe_to_seconds(self._config['timeframe'])) + maxsize=1000, ttl=timeframe_to_seconds(self._config.get('timeframe', '1h'))) def _set_dataframe_max_index(self, limit_index: int): """ @@ -271,9 +272,10 @@ class DataProvider: raise OperationalException(NO_EXCHANGE_EXCEPTION) return self._exchange.fetch_l2_order_book(pair, maximum) - def send_msg(self, message: str, always_send: bool = False) -> None: + def send_msg(self, message: str, *, always_send: bool = False) -> None: """ - TODO: Document me + Send custom RPC Notifications from your bot. + Will not send any bot in modes other than Dry-run or Live. :param message: Message to be sent. Must be below 4096. :param always_send: If False, will send the message only once per candle, and surpress identical messages. From 0adfa4d9efe26d9423d769ca8829e723569c0545 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Jul 2022 06:32:23 +0200 Subject: [PATCH 152/220] Add tests for dataprovider send-message methods --- tests/data/test_dataprovider.py | 19 +++++++++++++++++++ tests/rpc/test_rpc_manager.py | 21 +++++++++++++++++++-- tests/rpc/test_rpc_telegram.py | 10 ++++++++++ tests/test_freqtradebot.py | 6 ++++++ 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/tests/data/test_dataprovider.py b/tests/data/test_dataprovider.py index 93f82de5d..843d60786 100644 --- a/tests/data/test_dataprovider.py +++ b/tests/data/test_dataprovider.py @@ -311,3 +311,22 @@ def test_no_exchange_mode(default_conf): with pytest.raises(OperationalException, match=message): dp.available_pairs() + + +def test_dp_send_msg(default_conf): + + default_conf["runmode"] = RunMode.DRY_RUN + + default_conf["timeframe"] = '1h' + dp = DataProvider(default_conf, None) + msg = 'Test message' + dp.send_msg(msg) + + assert msg in dp._msg_queue + dp._msg_queue.pop() + assert msg not in dp._msg_queue + # Message is not resent due to caching + dp.send_msg(msg) + assert msg not in dp._msg_queue + dp.send_msg(msg, always_send=True) + assert msg in dp._msg_queue diff --git a/tests/rpc/test_rpc_manager.py b/tests/rpc/test_rpc_manager.py index 596b5ae20..b9ae16a20 100644 --- a/tests/rpc/test_rpc_manager.py +++ b/tests/rpc/test_rpc_manager.py @@ -1,6 +1,7 @@ # pragma pylint: disable=missing-docstring, C0103 import logging import time +from collections import deque from unittest.mock import MagicMock from freqtrade.enums import RPCMessageType @@ -81,9 +82,25 @@ def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None: assert telegram_mock.call_count == 0 +def test_process_msg_queue(mocker, default_conf, caplog) -> None: + telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg') + mocker.patch('freqtrade.rpc.telegram.Telegram._init') + + freqtradebot = get_patched_freqtradebot(mocker, default_conf) + rpc_manager = RPCManager(freqtradebot) + queue = deque() + queue.append('Test message') + queue.append('Test message 2') + rpc_manager.process_msg_queue(queue) + + assert log_has("Sending rpc message: {'type': strategy_msg, 'msg': 'Test message'}", caplog) + assert log_has("Sending rpc message: {'type': strategy_msg, 'msg': 'Test message 2'}", caplog) + assert telegram_mock.call_count == 2 + + def test_send_msg_telegram_enabled(mocker, default_conf, caplog) -> None: - telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock()) - mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock()) + telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg') + mocker.patch('freqtrade.rpc.telegram.Telegram._init') freqtradebot = get_patched_freqtradebot(mocker, default_conf) rpc_manager = RPCManager(freqtradebot) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index f69b7e878..8d244f3fd 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1994,6 +1994,16 @@ def test_startup_notification(default_conf, mocker) -> None: assert msg_mock.call_args[0][0] == '*Custom:* `Hello World`' +def test_send_msg_strategy_msg_notification(default_conf, mocker) -> None: + + telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) + telegram.send_msg({ + 'type': RPCMessageType.STRATEGY_MSG, + 'msg': 'hello world, Test msg' + }) + assert msg_mock.call_args[0][0] == 'hello world, Test msg' + + def test_send_msg_unknown_type(default_conf, mocker) -> None: telegram, _, _ = get_telegram_testobject(mocker, default_conf) with pytest.raises(NotImplementedError, match=r'Unknown message type: None'): diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 66cbd7d9b..438a2704c 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -68,6 +68,12 @@ def test_process_stopped(mocker, default_conf_usdt) -> None: assert coo_mock.call_count == 1 +def test_process_calls_sendmsg(mocker, default_conf_usdt) -> None: + freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) + freqtrade.process() + assert freqtrade.rpc.process_msg_queue.call_count == 1 + + def test_bot_cleanup(mocker, default_conf_usdt, caplog) -> None: mock_cleanup = mocker.patch('freqtrade.freqtradebot.cleanup_db') coo_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cancel_all_open_orders') From 2595e40e47f72970974fff7cc27331bf2387975a Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Jul 2022 06:47:16 +0200 Subject: [PATCH 153/220] Remove unused test-strategy --- tests/rpc/test_rpc_apiserver.py | 1 - .../strats/strategy_test_v3_analysis.py | 175 ------------------ tests/strategy/test_strategy_loading.py | 6 +- 3 files changed, 3 insertions(+), 179 deletions(-) delete mode 100644 tests/strategy/strats/strategy_test_v3_analysis.py diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 57c08f48e..57ba8e9f1 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1402,7 +1402,6 @@ def test_api_strategies(botclient): 'InformativeDecoratorTest', 'StrategyTestV2', 'StrategyTestV3', - 'StrategyTestV3Analysis', 'StrategyTestV3Futures' ]} diff --git a/tests/strategy/strats/strategy_test_v3_analysis.py b/tests/strategy/strats/strategy_test_v3_analysis.py deleted file mode 100644 index 290fef156..000000000 --- a/tests/strategy/strats/strategy_test_v3_analysis.py +++ /dev/null @@ -1,175 +0,0 @@ -# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement - -import talib.abstract as ta -from pandas import DataFrame - -import freqtrade.vendor.qtpylib.indicators as qtpylib -from freqtrade.strategy import (BooleanParameter, DecimalParameter, IntParameter, IStrategy, - RealParameter) - - -class StrategyTestV3Analysis(IStrategy): - """ - Strategy used by tests freqtrade bot. - Please do not modify this strategy, it's intended for internal use only. - Please look at the SampleStrategy in the user_data/strategy directory - or strategy repository https://github.com/freqtrade/freqtrade-strategies - for samples and inspiration. - """ - INTERFACE_VERSION = 3 - - # Minimal ROI designed for the strategy - minimal_roi = { - "40": 0.0, - "30": 0.01, - "20": 0.02, - "0": 0.04 - } - - # Optimal stoploss designed for the strategy - stoploss = -0.10 - - # Optimal timeframe for the strategy - timeframe = '5m' - - # Optional order type mapping - order_types = { - 'entry': 'limit', - 'exit': 'limit', - 'stoploss': 'limit', - 'stoploss_on_exchange': False - } - - # Number of candles the strategy requires before producing valid signals - startup_candle_count: int = 20 - - # Optional time in force for orders - order_time_in_force = { - 'entry': 'gtc', - 'exit': 'gtc', - } - - buy_params = { - 'buy_rsi': 35, - # Intentionally not specified, so "default" is tested - # 'buy_plusdi': 0.4 - } - - sell_params = { - 'sell_rsi': 74, - 'sell_minusdi': 0.4 - } - - buy_rsi = IntParameter([0, 50], default=30, space='buy') - buy_plusdi = RealParameter(low=0, high=1, default=0.5, space='buy') - sell_rsi = IntParameter(low=50, high=100, default=70, space='sell') - sell_minusdi = DecimalParameter(low=0, high=1, default=0.5001, decimals=3, space='sell', - load=False) - protection_enabled = BooleanParameter(default=True) - protection_cooldown_lookback = IntParameter([0, 50], default=30) - - # TODO: Can this work with protection tests? (replace HyperoptableStrategy implicitly ... ) - # @property - # def protections(self): - # prot = [] - # if self.protection_enabled.value: - # prot.append({ - # "method": "CooldownPeriod", - # "stop_duration_candles": self.protection_cooldown_lookback.value - # }) - # return prot - - bot_started = False - - def bot_start(self): - self.bot_started = True - - def informative_pairs(self): - - return [] - - def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - - # Momentum Indicator - # ------------------------------------ - - # ADX - dataframe['adx'] = ta.ADX(dataframe) - - # MACD - macd = ta.MACD(dataframe) - dataframe['macd'] = macd['macd'] - dataframe['macdsignal'] = macd['macdsignal'] - dataframe['macdhist'] = macd['macdhist'] - - # Minus Directional Indicator / Movement - dataframe['minus_di'] = ta.MINUS_DI(dataframe) - - # Plus Directional Indicator / Movement - dataframe['plus_di'] = ta.PLUS_DI(dataframe) - - # RSI - dataframe['rsi'] = ta.RSI(dataframe) - - # Stoch fast - stoch_fast = ta.STOCHF(dataframe) - dataframe['fastd'] = stoch_fast['fastd'] - dataframe['fastk'] = stoch_fast['fastk'] - - # Bollinger bands - bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) - dataframe['bb_lowerband'] = bollinger['lower'] - dataframe['bb_middleband'] = bollinger['mid'] - dataframe['bb_upperband'] = bollinger['upper'] - - # EMA - Exponential Moving Average - dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10) - - return dataframe - - def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - - dataframe.loc[ - ( - (dataframe['rsi'] < self.buy_rsi.value) & - (dataframe['fastd'] < 35) & - (dataframe['adx'] > 30) & - (dataframe['plus_di'] > self.buy_plusdi.value) - ) | - ( - (dataframe['adx'] > 65) & - (dataframe['plus_di'] > self.buy_plusdi.value) - ), - ['enter_long', 'enter_tag']] = 1, 'enter_tag_long' - - dataframe.loc[ - ( - qtpylib.crossed_below(dataframe['rsi'], self.sell_rsi.value) - ), - ['enter_short', 'enter_tag']] = 1, 'enter_tag_short' - - return dataframe - - def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe.loc[ - ( - ( - (qtpylib.crossed_above(dataframe['rsi'], self.sell_rsi.value)) | - (qtpylib.crossed_above(dataframe['fastd'], 70)) - ) & - (dataframe['adx'] > 10) & - (dataframe['minus_di'] > 0) - ) | - ( - (dataframe['adx'] > 70) & - (dataframe['minus_di'] > self.sell_minusdi.value) - ), - ['exit_long', 'exit_tag']] = 1, 'exit_tag_long' - - dataframe.loc[ - ( - qtpylib.crossed_above(dataframe['rsi'], self.buy_rsi.value) - ), - ['exit_long', 'exit_tag']] = 1, 'exit_tag_short' - - return dataframe diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py index bdfcf3211..666ae2b05 100644 --- a/tests/strategy/test_strategy_loading.py +++ b/tests/strategy/test_strategy_loading.py @@ -34,7 +34,7 @@ def test_search_all_strategies_no_failed(): directory = Path(__file__).parent / "strats" strategies = StrategyResolver.search_all_objects(directory, enum_failed=False) assert isinstance(strategies, list) - assert len(strategies) == 7 + assert len(strategies) == 6 assert isinstance(strategies[0], dict) @@ -42,10 +42,10 @@ def test_search_all_strategies_with_failed(): directory = Path(__file__).parent / "strats" strategies = StrategyResolver.search_all_objects(directory, enum_failed=True) assert isinstance(strategies, list) - assert len(strategies) == 8 + assert len(strategies) == 7 # with enum_failed=True search_all_objects() shall find 2 good strategies # and 1 which fails to load - assert len([x for x in strategies if x['class'] is not None]) == 7 + assert len([x for x in strategies if x['class'] is not None]) == 6 assert len([x for x in strategies if x['class'] is None]) == 1 From 31ddec834816d980d2802810868b62f44df787d1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Jul 2022 06:51:56 +0200 Subject: [PATCH 154/220] Add missing test to confirm backtesting won't send messages --- tests/data/test_dataprovider.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/data/test_dataprovider.py b/tests/data/test_dataprovider.py index 843d60786..49603feac 100644 --- a/tests/data/test_dataprovider.py +++ b/tests/data/test_dataprovider.py @@ -330,3 +330,8 @@ def test_dp_send_msg(default_conf): assert msg not in dp._msg_queue dp.send_msg(msg, always_send=True) assert msg in dp._msg_queue + + default_conf["runmode"] = RunMode.BACKTEST + dp = DataProvider(default_conf, None) + dp.send_msg(msg, always_send=True) + assert msg not in dp._msg_queue From cc3ead9d7bd289bfceb97a8c165b6b519b4710c4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Jul 2022 19:52:39 +0200 Subject: [PATCH 155/220] Set required_profit for stoploss guard, allowing to ignore small stoplosses. closes #7076 --- docs/includes/protections.md | 3 +++ freqtrade/plugins/protections/stoploss_guard.py | 5 +++-- tests/plugins/test_protections.py | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/includes/protections.md b/docs/includes/protections.md index d67924cfe..e0ad8189f 100644 --- a/docs/includes/protections.md +++ b/docs/includes/protections.md @@ -50,6 +50,8 @@ This applies across all pairs, unless `only_per_pair` is set to true, which will Similarly, this protection will by default look at all trades (long and short). For futures bots, setting `only_per_side` will make the bot only consider one side, and will then only lock this one side, allowing for example shorts to continue after a series of long stoplosses. +`required_profit` will determine the required relative profit (or loss) for stoplosses to consider. This should normally not be set and defaults to 0.0 - which means all losing stoplosses will be triggering a block. + The below example stops trading for all pairs for 4 candles after the last trade if the bot hit stoploss 4 times within the last 24 candles. ``` python @@ -61,6 +63,7 @@ def protections(self): "lookback_period_candles": 24, "trade_limit": 4, "stop_duration_candles": 4, + "required_profit": 0.0, "only_per_pair": False, "only_per_side": False } diff --git a/freqtrade/plugins/protections/stoploss_guard.py b/freqtrade/plugins/protections/stoploss_guard.py index 713a2da07..abc90a685 100644 --- a/freqtrade/plugins/protections/stoploss_guard.py +++ b/freqtrade/plugins/protections/stoploss_guard.py @@ -23,13 +23,14 @@ class StoplossGuard(IProtection): self._trade_limit = protection_config.get('trade_limit', 10) self._disable_global_stop = protection_config.get('only_per_pair', False) self._only_per_side = protection_config.get('only_per_side', False) + self._profit_limit = protection_config.get('required_profit', 0.0) def short_desc(self) -> str: """ Short method description - used for startup-messages """ return (f"{self.name} - Frequent Stoploss Guard, {self._trade_limit} stoplosses " - f"within {self.lookback_period_str}.") + f"with profit < {self._profit_limit:.2%} within {self.lookback_period_str}.") def _reason(self) -> str: """ @@ -49,7 +50,7 @@ class StoplossGuard(IProtection): trades = [trade for trade in trades1 if (str(trade.exit_reason) in ( ExitType.TRAILING_STOP_LOSS.value, ExitType.STOP_LOSS.value, ExitType.STOPLOSS_ON_EXCHANGE.value) - and trade.close_profit and trade.close_profit < 0)] + and trade.close_profit and trade.close_profit < self._profit_limit)] if self._only_per_side: # Long or short trades only diff --git a/tests/plugins/test_protections.py b/tests/plugins/test_protections.py index 3c333200c..4cebb6492 100644 --- a/tests/plugins/test_protections.py +++ b/tests/plugins/test_protections.py @@ -424,7 +424,7 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): @pytest.mark.parametrize("protectionconf,desc_expected,exception_expected", [ ({"method": "StoplossGuard", "lookback_period": 60, "trade_limit": 2, "stop_duration": 60}, "[{'StoplossGuard': 'StoplossGuard - Frequent Stoploss Guard, " - "2 stoplosses within 60 minutes.'}]", + "2 stoplosses with profit < 0.00% within 60 minutes.'}]", None ), ({"method": "CooldownPeriod", "stop_duration": 60}, @@ -442,9 +442,9 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): None ), ({"method": "StoplossGuard", "lookback_period_candles": 12, "trade_limit": 2, - "stop_duration": 60}, + "required_profit": -0.05, "stop_duration": 60}, "[{'StoplossGuard': 'StoplossGuard - Frequent Stoploss Guard, " - "2 stoplosses within 12 candles.'}]", + "2 stoplosses with profit < -5.00% within 12 candles.'}]", None ), ({"method": "CooldownPeriod", "stop_duration_candles": 5}, From d70650b074e023c649a04ce15ca84946b3409eb6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Jul 2022 08:20:22 +0200 Subject: [PATCH 156/220] Add note for plot-dataframe and current-whitelist closes #7142 --- docs/strategy-customization.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/strategy-customization.md b/docs/strategy-customization.md index 6947380dd..78256e0ee 100644 --- a/docs/strategy-customization.md +++ b/docs/strategy-customization.md @@ -646,6 +646,9 @@ This is where calling `self.dp.current_whitelist()` comes in handy. return informative_pairs ``` +??? Note "Plotting with current_whitelist" + Current whitelist is not supported for `plot-dataframe`, as this command is usually used by providing an explicit pairlist - and would therefore make the return values of this method misleading. + ### *get_pair_dataframe(pair, timeframe)* ``` python From 995be90f91a21c351a5c22264135694f3e11d62b Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Jul 2022 20:35:23 +0200 Subject: [PATCH 157/220] Liquidation should be a separate exit type --- freqtrade/enums/exittype.py | 1 + freqtrade/optimize/backtesting.py | 14 ++++++++++---- freqtrade/persistence/trade_model.py | 12 ++---------- freqtrade/plugins/protections/stoploss_guard.py | 2 +- freqtrade/strategy/interface.py | 13 ++++++++++++- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/freqtrade/enums/exittype.py b/freqtrade/enums/exittype.py index b2c5b62ea..1e15e70cd 100644 --- a/freqtrade/enums/exittype.py +++ b/freqtrade/enums/exittype.py @@ -9,6 +9,7 @@ class ExitType(Enum): STOP_LOSS = "stop_loss" STOPLOSS_ON_EXCHANGE = "stoploss_on_exchange" TRAILING_STOP_LOSS = "trailing_stop_loss" + LIQUIDATION = "liquidation" EXIT_SIGNAL = "exit_signal" FORCE_EXIT = "force_exit" EMERGENCY_EXIT = "emergency_exit" diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 4d16dc0f1..598ce6710 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -381,7 +381,8 @@ class Backtesting: Get close rate for backtesting result """ # Special handling if high or low hit STOP_LOSS or ROI - if exit.exit_type in (ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS): + if exit.exit_type in ( + ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS, ExitType.LIQUIDATION): return self._get_close_rate_for_stoploss(row, trade, exit, trade_dur) elif exit.exit_type == (ExitType.ROI): return self._get_close_rate_for_roi(row, trade, exit, trade_dur) @@ -396,11 +397,16 @@ class Backtesting: is_short = trade.is_short or False leverage = trade.leverage or 1.0 side_1 = -1 if is_short else 1 + if exit.exit_type == ExitType.LIQUIDATION and trade.liquidation_price: + stoploss_value = trade.liquidation_price + else: + stoploss_value = trade.stop_loss + if is_short: - if trade.stop_loss < row[LOW_IDX]: + if stoploss_value < row[LOW_IDX]: return row[OPEN_IDX] else: - if trade.stop_loss > row[HIGH_IDX]: + if stoploss_value > row[HIGH_IDX]: return row[OPEN_IDX] # Special case: trailing triggers within same candle as trade opened. Assume most @@ -433,7 +439,7 @@ class Backtesting: return max(row[LOW_IDX], stop_rate) # Set close_rate to stoploss - return trade.stop_loss + return stoploss_value def _get_close_rate_for_roi(self, row: Tuple, trade: LocalTrade, exit: ExitCheckTuple, trade_dur: int) -> float: diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 5f302de71..2ff65d9d0 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -511,17 +511,9 @@ class LocalTrade(): Method you should use to set self.stop_loss. Assures stop_loss is not passed the liquidation price """ - if self.liquidation_price is not None: - if self.is_short: - sl = min(stop_loss, self.liquidation_price) - else: - sl = max(stop_loss, self.liquidation_price) - else: - sl = stop_loss - if not self.stop_loss: - self.initial_stop_loss = sl - self.stop_loss = sl + self.initial_stop_loss = stop_loss + self.stop_loss = stop_loss self.stop_loss_pct = -1 * abs(percent) self.stoploss_last_update = datetime.utcnow() diff --git a/freqtrade/plugins/protections/stoploss_guard.py b/freqtrade/plugins/protections/stoploss_guard.py index abc90a685..e80d13e9d 100644 --- a/freqtrade/plugins/protections/stoploss_guard.py +++ b/freqtrade/plugins/protections/stoploss_guard.py @@ -49,7 +49,7 @@ class StoplossGuard(IProtection): trades1 = Trade.get_trades_proxy(pair=pair, is_open=False, close_date=look_back_until) trades = [trade for trade in trades1 if (str(trade.exit_reason) in ( ExitType.TRAILING_STOP_LOSS.value, ExitType.STOP_LOSS.value, - ExitType.STOPLOSS_ON_EXCHANGE.value) + ExitType.STOPLOSS_ON_EXCHANGE.value, ExitType.LIQUIDATION.value) and trade.close_profit and trade.close_profit < self._profit_limit)] if self._only_per_side: diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index c60817c99..f50721583 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -963,7 +963,7 @@ class IStrategy(ABC, HyperStrategyMixin): # ROI # Trailing stoploss - if stoplossflag.exit_type == ExitType.STOP_LOSS: + if stoplossflag.exit_type in (ExitType.STOP_LOSS, ExitType.LIQUIDATION): logger.debug(f"{trade.pair} - Stoploss hit. exit_type={stoplossflag.exit_type}") exits.append(stoplossflag) @@ -1035,6 +1035,17 @@ class IStrategy(ABC, HyperStrategyMixin): sl_higher_long = (trade.stop_loss >= (low or current_rate) and not trade.is_short) sl_lower_short = (trade.stop_loss <= (high or current_rate) and trade.is_short) + liq_higher_long = (trade.liquidation_price + and trade.liquidation_price >= (low or current_rate) + and not trade.is_short) + liq_lower_short = (trade.liquidation_price + and trade.liquidation_price <= (high or current_rate) + and trade.is_short) + + if (liq_higher_long or liq_lower_short): + logger.debug(f"{trade.pair} - Liquidation price hit. exit_type=ExitType.LIQUIDATION") + return ExitCheckTuple(exit_type=ExitType.LIQUIDATION) + # evaluate if the stoploss was hit if stoploss is not on exchange # in Dry-Run, this handles stoploss logic as well, as the logic will not be different to # regular stoploss handling. From 8711b7d99f224b3d0ee26553e32774dd247d605a Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Jul 2022 20:37:10 +0200 Subject: [PATCH 158/220] Liquidations cannot be rejected. --- freqtrade/freqtradebot.py | 5 +++-- freqtrade/optimize/backtesting.py | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 43608cae7..d58c05d7f 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1463,11 +1463,12 @@ class FreqtradeBot(LoggingMixin): amount = self._safe_exit_amount(trade.pair, trade.amount) time_in_force = self.strategy.order_time_in_force['exit'] - if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( + if (exit_check.exit_type != ExitType.LIQUIDATION and not strategy_safe_wrapper( + self.strategy.confirm_trade_exit, default_retval=True)( pair=trade.pair, trade=trade, order_type=order_type, amount=amount, rate=limit, time_in_force=time_in_force, exit_reason=exit_reason, sell_reason=exit_reason, # sellreason -> compatibility - current_time=datetime.now(timezone.utc)): + current_time=datetime.now(timezone.utc))): logger.info(f"User denied exit for {trade.pair}.") return False diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 598ce6710..6bbace185 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -598,7 +598,8 @@ class Backtesting: # Confirm trade exit: time_in_force = self.strategy.order_time_in_force['exit'] - if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( + if (exit_.exit_type != ExitType.LIQUIDATION and not strategy_safe_wrapper( + self.strategy.confirm_trade_exit, default_retval=True)( pair=trade.pair, trade=trade, # type: ignore[arg-type] order_type='limit', @@ -607,7 +608,7 @@ class Backtesting: time_in_force=time_in_force, sell_reason=exit_reason, # deprecated exit_reason=exit_reason, - current_time=exit_candle_time): + current_time=exit_candle_time)): return None trade.exit_reason = exit_reason From f57ecb18615dc2e75fc73d0da78540ea0ebd6804 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Jul 2022 06:55:42 +0200 Subject: [PATCH 159/220] Simplify adjust_stop test --- tests/test_persistence.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 838c4c22a..4703075eb 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -1537,26 +1537,26 @@ def test_adjust_stop_loss(fee): # Get percent of profit with a custom rate (Higher than open rate) trade.adjust_stop_loss(1.3, -0.1) - assert round(trade.stop_loss, 8) == 1.17 + assert pytest.approx(trade.stop_loss) == 1.17 assert trade.stop_loss_pct == -0.1 assert trade.initial_stop_loss == 0.95 assert trade.initial_stop_loss_pct == -0.05 # current rate lower again ... should not change trade.adjust_stop_loss(1.2, 0.1) - assert round(trade.stop_loss, 8) == 1.17 + assert pytest.approx(trade.stop_loss) == 1.17 assert trade.initial_stop_loss == 0.95 assert trade.initial_stop_loss_pct == -0.05 # current rate higher... should raise stoploss trade.adjust_stop_loss(1.4, 0.1) - assert round(trade.stop_loss, 8) == 1.26 + assert pytest.approx(trade.stop_loss) == 1.26 assert trade.initial_stop_loss == 0.95 assert trade.initial_stop_loss_pct == -0.05 # Initial is true but stop_loss set - so doesn't do anything trade.adjust_stop_loss(1.7, 0.1, True) - assert round(trade.stop_loss, 8) == 1.26 + assert pytest.approx(trade.stop_loss) == 1.26 assert trade.initial_stop_loss == 0.95 assert trade.initial_stop_loss_pct == -0.05 assert trade.stop_loss_pct == -0.1 From 9852733ef7f7284765b8092eb6cd27edd2b7c0e8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Jul 2022 06:58:59 +0200 Subject: [PATCH 160/220] Improve tests to align with modified logic --- freqtrade/persistence/trade_model.py | 6 ------ tests/test_persistence.py | 17 ++++++++++------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 2ff65d9d0..919750886 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -535,14 +535,8 @@ class LocalTrade(): leverage = self.leverage or 1.0 if self.is_short: new_loss = float(current_price * (1 + abs(stoploss / leverage))) - # If trading with leverage, don't set the stoploss below the liquidation price - if self.liquidation_price: - new_loss = min(self.liquidation_price, new_loss) else: new_loss = float(current_price * (1 - abs(stoploss / leverage))) - # If trading with leverage, don't set the stoploss below the liquidation price - if self.liquidation_price: - new_loss = max(self.liquidation_price, new_loss) # no stop loss assigned yet if self.initial_stop_loss_pct is None or refresh: diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 4703075eb..5476e1d50 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -133,13 +133,14 @@ def test_set_stop_loss_isolated_liq(fee): trade.set_isolated_liq(0.11) trade._set_stop_loss(0.1, 0) assert trade.liquidation_price == 0.11 - assert trade.stop_loss == 0.11 + # Stoploss does not change from liquidation price + assert trade.stop_loss == 0.1 assert trade.initial_stop_loss == 0.1 # lower stop doesn't move stoploss trade._set_stop_loss(0.1, 0) assert trade.liquidation_price == 0.11 - assert trade.stop_loss == 0.11 + assert trade.stop_loss == 0.1 assert trade.initial_stop_loss == 0.1 trade.stop_loss = None @@ -174,13 +175,14 @@ def test_set_stop_loss_isolated_liq(fee): trade.set_isolated_liq(0.07) trade._set_stop_loss(0.1, (1.0 / 8.0)) assert trade.liquidation_price == 0.07 - assert trade.stop_loss == 0.07 + # Stoploss does not change from liquidation price + assert trade.stop_loss == 0.1 assert trade.initial_stop_loss == 0.08 # Stop doesn't move stop higher trade._set_stop_loss(0.1, (1.0 / 9.0)) assert trade.liquidation_price == 0.07 - assert trade.stop_loss == 0.07 + assert trade.stop_loss == 0.1 assert trade.initial_stop_loss == 0.08 @@ -1609,9 +1611,10 @@ def test_adjust_stop_loss_short(fee): assert trade.initial_stop_loss == 1.05 assert trade.initial_stop_loss_pct == -0.05 assert trade.stop_loss_pct == -0.1 + # Liquidation price is lower than stoploss - so liquidation would trigger first. trade.set_isolated_liq(0.63) trade.adjust_stop_loss(0.59, -0.1) - assert trade.stop_loss == 0.63 + assert trade.stop_loss == 0.649 assert trade.liquidation_price == 0.63 @@ -2011,8 +2014,8 @@ def test_stoploss_reinitialization_short(default_conf, fee): # Stoploss can't go above liquidation price trade_adj.set_isolated_liq(0.985) trade.adjust_stop_loss(0.9799, -0.05) - assert trade_adj.stop_loss == 0.985 - assert trade_adj.stop_loss == 0.985 + assert trade_adj.stop_loss == 0.989699 + assert trade_adj.liquidation_price == 0.985 def test_update_fee(fee): From ff4cc5d3165b53058c1b80f8f94bb16df2345269 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Jul 2022 07:14:25 +0200 Subject: [PATCH 161/220] Revamp liquidation test to actually make sense --- tests/test_persistence.py | 79 +++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 5476e1d50..5dbd6b86b 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -120,70 +120,83 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.stop_loss is None assert trade.initial_stop_loss is None - trade._set_stop_loss(0.1, (1.0 / 9.0)) + trade.adjust_stop_loss(2.0, 0.2, True) assert trade.liquidation_price == 0.09 - assert trade.stop_loss == 0.1 - assert trade.initial_stop_loss == 0.1 + assert trade.stop_loss == 1.8 + assert trade.initial_stop_loss == 1.8 trade.set_isolated_liq(0.08) assert trade.liquidation_price == 0.08 - assert trade.stop_loss == 0.1 - assert trade.initial_stop_loss == 0.1 + assert trade.stop_loss == 1.8 + assert trade.initial_stop_loss == 1.8 trade.set_isolated_liq(0.11) - trade._set_stop_loss(0.1, 0) + trade.adjust_stop_loss(2.0, 0.2) assert trade.liquidation_price == 0.11 # Stoploss does not change from liquidation price - assert trade.stop_loss == 0.1 - assert trade.initial_stop_loss == 0.1 + assert trade.stop_loss == 1.8 + assert trade.initial_stop_loss == 1.8 # lower stop doesn't move stoploss - trade._set_stop_loss(0.1, 0) + trade.adjust_stop_loss(1.8, 0.2) assert trade.liquidation_price == 0.11 - assert trade.stop_loss == 0.1 - assert trade.initial_stop_loss == 0.1 + assert trade.stop_loss == 1.8 + assert trade.initial_stop_loss == 1.8 + + # higher stop does move stoploss + trade.adjust_stop_loss(2.1, 0.1) + assert trade.liquidation_price == 0.11 + assert pytest.approx(trade.stop_loss) == 1.994999 + assert trade.initial_stop_loss == 1.8 trade.stop_loss = None trade.liquidation_price = None trade.initial_stop_loss = None + trade.initial_stop_loss_pct = None - trade._set_stop_loss(0.07, 0) + trade.adjust_stop_loss(2.0, 0.1, True) assert trade.liquidation_price is None - assert trade.stop_loss == 0.07 - assert trade.initial_stop_loss == 0.07 + assert trade.stop_loss == 1.9 + assert trade.initial_stop_loss == 1.9 trade.is_short = True trade.recalc_open_trade_value() trade.stop_loss = None trade.initial_stop_loss = None + trade.initial_stop_loss_pct = None - trade.set_isolated_liq(0.09) - assert trade.liquidation_price == 0.09 + trade.set_isolated_liq(3.09) + assert trade.liquidation_price == 3.09 assert trade.stop_loss is None assert trade.initial_stop_loss is None - trade._set_stop_loss(0.08, (1.0 / 9.0)) - assert trade.liquidation_price == 0.09 - assert trade.stop_loss == 0.08 - assert trade.initial_stop_loss == 0.08 + trade.adjust_stop_loss(2.0, 0.2) + assert trade.liquidation_price == 3.09 + assert trade.stop_loss == 2.2 + assert trade.initial_stop_loss == 2.2 - trade.set_isolated_liq(0.1) - assert trade.liquidation_price == 0.1 - assert trade.stop_loss == 0.08 - assert trade.initial_stop_loss == 0.08 + trade.set_isolated_liq(3.1) + assert trade.liquidation_price == 3.1 + assert trade.stop_loss == 2.2 + assert trade.initial_stop_loss == 2.2 - trade.set_isolated_liq(0.07) - trade._set_stop_loss(0.1, (1.0 / 8.0)) - assert trade.liquidation_price == 0.07 + trade.set_isolated_liq(3.8) + assert trade.liquidation_price == 3.8 # Stoploss does not change from liquidation price - assert trade.stop_loss == 0.1 - assert trade.initial_stop_loss == 0.08 + assert trade.stop_loss == 2.2 + assert trade.initial_stop_loss == 2.2 # Stop doesn't move stop higher - trade._set_stop_loss(0.1, (1.0 / 9.0)) - assert trade.liquidation_price == 0.07 - assert trade.stop_loss == 0.1 - assert trade.initial_stop_loss == 0.08 + trade.adjust_stop_loss(2.0, 0.3) + assert trade.liquidation_price == 3.8 + assert trade.stop_loss == 2.2 + assert trade.initial_stop_loss == 2.2 + + # Stoploss does move lower + trade.adjust_stop_loss(1.8, 0.1) + assert trade.liquidation_price == 3.8 + assert pytest.approx(trade.stop_loss) == 1.89 + assert trade.initial_stop_loss == 2.2 @pytest.mark.parametrize('exchange,is_short,lev,minutes,rate,interest,trading_mode', [ From 15752ce3c2d4b2131e9141c3aa496dda25c5d9d7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Jul 2022 07:15:01 +0200 Subject: [PATCH 162/220] Rename set_stoploss method to be fully private --- freqtrade/persistence/trade_model.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 919750886..1b8bcc42f 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -506,10 +506,9 @@ class LocalTrade(): return self.liquidation_price = liquidation_price - def _set_stop_loss(self, stop_loss: float, percent: float): + def __set_stop_loss(self, stop_loss: float, percent: float): """ - Method you should use to set self.stop_loss. - Assures stop_loss is not passed the liquidation price + Method used internally to set self.stop_loss. """ if not self.stop_loss: self.initial_stop_loss = stop_loss @@ -540,7 +539,7 @@ class LocalTrade(): # no stop loss assigned yet if self.initial_stop_loss_pct is None or refresh: - self._set_stop_loss(new_loss, stoploss) + self.__set_stop_loss(new_loss, stoploss) self.initial_stop_loss = new_loss self.initial_stop_loss_pct = -1 * abs(stoploss) @@ -555,7 +554,7 @@ class LocalTrade(): # ? decreasing the minimum stoploss if (higher_stop and not self.is_short) or (lower_stop and self.is_short): logger.debug(f"{self.pair} - Adjusting stoploss...") - self._set_stop_loss(new_loss, stoploss) + self.__set_stop_loss(new_loss, stoploss) else: logger.debug(f"{self.pair} - Keeping current stoploss...") From 4da96bc511c1a01ee717f304d60696141797d200 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Jul 2022 07:27:24 +0200 Subject: [PATCH 163/220] Update docs --- docs/strategy-callbacks.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index f584bd1bb..59d221bfc 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -623,6 +623,7 @@ class AwesomeStrategy(IStrategy): !!! Warning `confirm_trade_exit()` can prevent stoploss exits, causing significant losses as this would ignore stoploss exits. + `confirm_trade_exit()` will not be called for Liquidations - as liquidations are forced by the exchange, and therefore cannot be rejected. ## Adjust trade position From 845cecd38fe0acfed72d99eddccc5aea37234cfc Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Jul 2022 08:12:48 +0200 Subject: [PATCH 164/220] Add stoploss or liquidation property --- freqtrade/persistence/trade_model.py | 10 ++++++++++ freqtrade/strategy/interface.py | 7 ------- tests/test_persistence.py | 10 +++++++++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 1b8bcc42f..244ca79cd 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -302,6 +302,16 @@ class LocalTrade(): # Futures properties funding_fees: Optional[float] = None + @property + def stoploss_or_liquidation(self) -> float: + if self.liquidation_price: + if self.is_short: + return min(self.stop_loss, self.liquidation_price) + else: + return max(self.stop_loss, self.liquidation_price) + + return self.stop_loss + @property def buy_tag(self) -> Optional[str]: """ diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index f50721583..824f31258 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -1063,13 +1063,6 @@ class IStrategy(ABC, HyperStrategyMixin): f"stoploss is {trade.stop_loss:.6f}, " f"initial stoploss was at {trade.initial_stop_loss:.6f}, " f"trade opened at {trade.open_rate:.6f}") - new_stoploss = ( - trade.stop_loss + trade.initial_stop_loss - if trade.is_short else - trade.stop_loss - trade.initial_stop_loss - ) - logger.debug(f"{trade.pair} - Trailing stop saved " - f"{new_stoploss:.6f}") return ExitCheckTuple(exit_type=exit_type) diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 5dbd6b86b..3eca035c9 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -148,6 +148,7 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.liquidation_price == 0.11 assert pytest.approx(trade.stop_loss) == 1.994999 assert trade.initial_stop_loss == 1.8 + assert trade.stoploss_or_liquidation == trade.stop_loss trade.stop_loss = None trade.liquidation_price = None @@ -158,6 +159,7 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.liquidation_price is None assert trade.stop_loss == 1.9 assert trade.initial_stop_loss == 1.9 + assert trade.stoploss_or_liquidation == 1.9 trade.is_short = True trade.recalc_open_trade_value() @@ -174,11 +176,13 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.liquidation_price == 3.09 assert trade.stop_loss == 2.2 assert trade.initial_stop_loss == 2.2 + assert trade.stoploss_or_liquidation == 2.2 trade.set_isolated_liq(3.1) assert trade.liquidation_price == 3.1 assert trade.stop_loss == 2.2 assert trade.initial_stop_loss == 2.2 + assert trade.stoploss_or_liquidation == 2.2 trade.set_isolated_liq(3.8) assert trade.liquidation_price == 3.8 @@ -193,10 +197,14 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.initial_stop_loss == 2.2 # Stoploss does move lower + trade.set_isolated_liq(1.5) trade.adjust_stop_loss(1.8, 0.1) - assert trade.liquidation_price == 3.8 + assert trade.liquidation_price == 1.5 assert pytest.approx(trade.stop_loss) == 1.89 assert trade.initial_stop_loss == 2.2 + assert trade.stoploss_or_liquidation == 1.5 + + @pytest.mark.parametrize('exchange,is_short,lev,minutes,rate,interest,trading_mode', [ From dba7a7257dec1371c1bea14c099dbca06474e3ff Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Jul 2022 09:18:15 +0200 Subject: [PATCH 165/220] Use stop_or_liquidation instead of stop_loss --- freqtrade/freqtradebot.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index d58c05d7f..7440212c3 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1015,7 +1015,7 @@ class FreqtradeBot(LoggingMixin): trade.stoploss_order_id = None logger.error(f'Unable to place a stoploss order on exchange. {e}') logger.warning('Exiting the trade forcefully') - self.execute_trade_exit(trade, trade.stop_loss, exit_check=ExitCheckTuple( + self.execute_trade_exit(trade, stop_price, exit_check=ExitCheckTuple( exit_type=ExitType.EMERGENCY_EXIT)) except ExchangeError: @@ -1114,7 +1114,7 @@ class FreqtradeBot(LoggingMixin): :param order: Current on exchange stoploss order :return: None """ - stoploss_norm = self.exchange.price_to_precision(trade.pair, trade.stop_loss) + stoploss_norm = self.exchange.price_to_precision(trade.pair, trade.stoploss_or_liquidation) if self.exchange.stoploss_adjust(stoploss_norm, order, side=trade.exit_side): # we check if the update is necessary @@ -1132,7 +1132,7 @@ class FreqtradeBot(LoggingMixin): f"for pair {trade.pair}") # Create new stoploss order - if not self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss): + if not self.create_stoploss_order(trade=trade, stop_price=stoploss_norm): logger.warning(f"Could not create trailing stoploss order " f"for pair {trade.pair}.") @@ -1431,14 +1431,15 @@ class FreqtradeBot(LoggingMixin): ) exit_type = 'exit' exit_reason = exit_tag or exit_check.exit_reason - if exit_check.exit_type in (ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS): + if exit_check.exit_type in ( + ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS, ExitType.LIQUIDATION): exit_type = 'stoploss' # if stoploss is on exchange and we are on dry_run mode, # we consider the sell price stop price if (self.config['dry_run'] and exit_type == 'stoploss' and self.strategy.order_types['stoploss_on_exchange']): - limit = trade.stop_loss + limit = trade.stoploss_or_liquidation # set custom_exit_price if available proposed_limit_rate = limit From d046f0cc5e766ec24f5c88fd967b44ea88698481 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Jul 2022 09:19:48 +0200 Subject: [PATCH 166/220] Improve method wording for liquidation price setter --- freqtrade/freqtradebot.py | 4 ++-- freqtrade/optimize/backtesting.py | 2 +- freqtrade/persistence/trade_model.py | 2 +- tests/test_persistence.py | 22 ++++++++++------------ 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 7440212c3..3490b58d6 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1085,7 +1085,7 @@ class FreqtradeBot(LoggingMixin): if (trade.is_open and stoploss_order and stoploss_order['status'] in ('canceled', 'cancelled')): - if self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss): + if self.create_stoploss_order(trade=trade, stop_price=trade.stoploss_or_liquidation): return False else: trade.stoploss_order_id = None @@ -1662,7 +1662,7 @@ class FreqtradeBot(LoggingMixin): trade = self.cancel_stoploss_on_exchange(trade) # TODO: Margin will need to use interest_rate as well. # interest_rate = self.exchange.get_interest_rate() - trade.set_isolated_liq(self.exchange.get_liquidation_price( + trade.set_liquidation_price(self.exchange.get_liquidation_price( leverage=trade.leverage, pair=trade.pair, amount=trade.amount, diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 6bbace185..2c6cfb0e9 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -814,7 +814,7 @@ class Backtesting: trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss, initial=True) - trade.set_isolated_liq(self.exchange.get_liquidation_price( + trade.set_liquidation_price(self.exchange.get_liquidation_price( pair=pair, open_rate=propose_rate, amount=amount, diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 244ca79cd..44e148a0c 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -507,7 +507,7 @@ class LocalTrade(): self.max_rate = max(current_price, self.max_rate or self.open_rate) self.min_rate = min(current_price_low, self.min_rate or self.open_rate) - def set_isolated_liq(self, liquidation_price: Optional[float]): + def set_liquidation_price(self, liquidation_price: Optional[float]): """ Method you should use to set self.liquidation price. Assures stop_loss is not passed the liquidation price diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 3eca035c9..0c1fc01a5 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -99,7 +99,7 @@ def test_enter_exit_side(fee, is_short): @pytest.mark.usefixtures("init_persistence") -def test_set_stop_loss_isolated_liq(fee): +def test_set_stop_loss_liquidation(fee): trade = Trade( id=2, pair='ADA/USDT', @@ -115,7 +115,7 @@ def test_set_stop_loss_isolated_liq(fee): leverage=2.0, trading_mode=margin ) - trade.set_isolated_liq(0.09) + trade.set_liquidation_price(0.09) assert trade.liquidation_price == 0.09 assert trade.stop_loss is None assert trade.initial_stop_loss is None @@ -125,12 +125,12 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.stop_loss == 1.8 assert trade.initial_stop_loss == 1.8 - trade.set_isolated_liq(0.08) + trade.set_liquidation_price(0.08) assert trade.liquidation_price == 0.08 assert trade.stop_loss == 1.8 assert trade.initial_stop_loss == 1.8 - trade.set_isolated_liq(0.11) + trade.set_liquidation_price(0.11) trade.adjust_stop_loss(2.0, 0.2) assert trade.liquidation_price == 0.11 # Stoploss does not change from liquidation price @@ -167,7 +167,7 @@ def test_set_stop_loss_isolated_liq(fee): trade.initial_stop_loss = None trade.initial_stop_loss_pct = None - trade.set_isolated_liq(3.09) + trade.set_liquidation_price(3.09) assert trade.liquidation_price == 3.09 assert trade.stop_loss is None assert trade.initial_stop_loss is None @@ -178,13 +178,13 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.initial_stop_loss == 2.2 assert trade.stoploss_or_liquidation == 2.2 - trade.set_isolated_liq(3.1) + trade.set_liquidation_price(3.1) assert trade.liquidation_price == 3.1 assert trade.stop_loss == 2.2 assert trade.initial_stop_loss == 2.2 assert trade.stoploss_or_liquidation == 2.2 - trade.set_isolated_liq(3.8) + trade.set_liquidation_price(3.8) assert trade.liquidation_price == 3.8 # Stoploss does not change from liquidation price assert trade.stop_loss == 2.2 @@ -197,7 +197,7 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.initial_stop_loss == 2.2 # Stoploss does move lower - trade.set_isolated_liq(1.5) + trade.set_liquidation_price(1.5) trade.adjust_stop_loss(1.8, 0.1) assert trade.liquidation_price == 1.5 assert pytest.approx(trade.stop_loss) == 1.89 @@ -205,8 +205,6 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.stoploss_or_liquidation == 1.5 - - @pytest.mark.parametrize('exchange,is_short,lev,minutes,rate,interest,trading_mode', [ ("binance", False, 3, 10, 0.0005, round(0.0008333333333333334, 8), margin), ("binance", True, 3, 10, 0.0005, 0.000625, margin), @@ -1633,7 +1631,7 @@ def test_adjust_stop_loss_short(fee): assert trade.initial_stop_loss_pct == -0.05 assert trade.stop_loss_pct == -0.1 # Liquidation price is lower than stoploss - so liquidation would trigger first. - trade.set_isolated_liq(0.63) + trade.set_liquidation_price(0.63) trade.adjust_stop_loss(0.59, -0.1) assert trade.stop_loss == 0.649 assert trade.liquidation_price == 0.63 @@ -2033,7 +2031,7 @@ def test_stoploss_reinitialization_short(default_conf, fee): assert trade_adj.initial_stop_loss == 1.01 assert trade_adj.initial_stop_loss_pct == -0.05 # Stoploss can't go above liquidation price - trade_adj.set_isolated_liq(0.985) + trade_adj.set_liquidation_price(0.985) trade.adjust_stop_loss(0.9799, -0.05) assert trade_adj.stop_loss == 0.989699 assert trade_adj.liquidation_price == 0.985 From dc82675f00e5ed1b006eeb1490a3f14147cde979 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Jul 2022 17:28:16 +0200 Subject: [PATCH 167/220] Add Test for liquidation in stop-loss-reached --- tests/strategy/test_interface.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/tests/strategy/test_interface.py b/tests/strategy/test_interface.py index f6996a7a2..4257b2cf9 100644 --- a/tests/strategy/test_interface.py +++ b/tests/strategy/test_interface.py @@ -408,28 +408,31 @@ def test_min_roi_reached3(default_conf, fee) -> None: @pytest.mark.parametrize( - 'profit,adjusted,expected,trailing,custom,profit2,adjusted2,expected2,custom_stop', [ + 'profit,adjusted,expected,liq,trailing,custom,profit2,adjusted2,expected2,custom_stop', [ # Profit, adjusted stoploss(absolute), profit for 2nd call, enable trailing, # enable custom stoploss, expected after 1st call, expected after 2nd call - (0.2, 0.9, ExitType.NONE, False, False, 0.3, 0.9, ExitType.NONE, None), - (0.2, 0.9, ExitType.NONE, False, False, -0.2, 0.9, ExitType.STOP_LOSS, None), - (0.2, 1.14, ExitType.NONE, True, False, 0.05, 1.14, ExitType.TRAILING_STOP_LOSS, None), - (0.01, 0.96, ExitType.NONE, True, False, 0.05, 1, ExitType.NONE, None), - (0.05, 1, ExitType.NONE, True, False, -0.01, 1, ExitType.TRAILING_STOP_LOSS, None), + (0.2, 0.9, ExitType.NONE, None, False, False, 0.3, 0.9, ExitType.NONE, None), + (0.2, 0.9, ExitType.NONE, None, False, False, -0.2, 0.9, ExitType.STOP_LOSS, None), + (0.2, 0.9, ExitType.NONE, 0.8, False, False, -0.2, 0.9, ExitType.LIQUIDATION, None), + (0.2, 1.14, ExitType.NONE, None, True, False, 0.05, 1.14, ExitType.TRAILING_STOP_LOSS, + None), + (0.01, 0.96, ExitType.NONE, None, True, False, 0.05, 1, ExitType.NONE, None), + (0.05, 1, ExitType.NONE, None, True, False, -0.01, 1, ExitType.TRAILING_STOP_LOSS, None), # Default custom case - trails with 10% - (0.05, 0.95, ExitType.NONE, False, True, -0.02, 0.95, ExitType.NONE, None), - (0.05, 0.95, ExitType.NONE, False, True, -0.06, 0.95, ExitType.TRAILING_STOP_LOSS, None), - (0.05, 1, ExitType.NONE, False, True, -0.06, 1, ExitType.TRAILING_STOP_LOSS, + (0.05, 0.95, ExitType.NONE, None, False, True, -0.02, 0.95, ExitType.NONE, None), + (0.05, 0.95, ExitType.NONE, None, False, True, -0.06, 0.95, ExitType.TRAILING_STOP_LOSS, + None), + (0.05, 1, ExitType.NONE, None, False, True, -0.06, 1, ExitType.TRAILING_STOP_LOSS, lambda **kwargs: -0.05), - (0.05, 1, ExitType.NONE, False, True, 0.09, 1.04, ExitType.NONE, + (0.05, 1, ExitType.NONE, None, False, True, 0.09, 1.04, ExitType.NONE, lambda **kwargs: -0.05), - (0.05, 0.95, ExitType.NONE, False, True, 0.09, 0.98, ExitType.NONE, + (0.05, 0.95, ExitType.NONE, None, False, True, 0.09, 0.98, ExitType.NONE, lambda current_profit, **kwargs: -0.1 if current_profit < 0.6 else -(current_profit * 2)), # Error case - static stoploss in place - (0.05, 0.9, ExitType.NONE, False, True, 0.09, 0.9, ExitType.NONE, + (0.05, 0.9, ExitType.NONE, None, False, True, 0.09, 0.9, ExitType.NONE, lambda **kwargs: None), ]) -def test_stop_loss_reached(default_conf, fee, profit, adjusted, expected, trailing, custom, +def test_stop_loss_reached(default_conf, fee, profit, adjusted, expected, liq, trailing, custom, profit2, adjusted2, expected2, custom_stop) -> None: strategy = StrategyResolver.load_strategy(default_conf) @@ -442,6 +445,7 @@ def test_stop_loss_reached(default_conf, fee, profit, adjusted, expected, traili fee_close=fee.return_value, exchange='binance', open_rate=1, + liquidation_price=liq, ) trade.adjust_min_max_rates(trade.open_rate, trade.open_rate) strategy.trailing_stop = trailing From bad15f077c66710314b7dea75d0e5f7abee767a3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Jul 2022 17:49:06 +0200 Subject: [PATCH 168/220] Simplify fetch_positions by using already existing method --- freqtrade/exchange/exchange.py | 33 ++++++++++++++++----------------- tests/exchange/test_exchange.py | 14 -------------- 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 79bc769e6..e180c90b2 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1332,11 +1332,19 @@ class Exchange: raise OperationalException(e) from e @retrier - def fetch_positions(self) -> List[Dict]: + def fetch_positions(self, pair: str = None) -> List[Dict]: + """ + Fetch positions from the exchange. + If no pair is given, all positions are returned. + :param pair: Pair for the query + """ if self._config['dry_run'] or self.trading_mode != TradingMode.FUTURES: return [] try: - positions: List[Dict] = self._api.fetch_positions() + symbols = [] + if pair: + symbols.append(pair) + positions: List[Dict] = self._api.fetch_positions(symbols) self._log_exchange_response('fetch_positions', positions) return positions except ccxt.DDoSProtection as e: @@ -2539,7 +2547,6 @@ class Exchange: else: return 0.0 - @retrier def get_or_calculate_liquidation_price( self, pair: str, @@ -2573,20 +2580,12 @@ class Exchange: upnl_ex_1=upnl_ex_1 ) else: - try: - positions = self._api.fetch_positions([pair]) - if len(positions) > 0: - pos = positions[0] - isolated_liq = pos['liquidationPrice'] - else: - return None - except ccxt.DDoSProtection as e: - raise DDosProtection(e) from e - except (ccxt.NetworkError, ccxt.ExchangeError) as e: - raise TemporaryError( - f'Could not set margin mode due to {e.__class__.__name__}. Message: {e}') from e - except ccxt.BaseError as e: - raise OperationalException(e) from e + positions = self.fetch_positions(pair) + if len(positions) > 0: + pos = positions[0] + isolated_liq = pos['liquidationPrice'] + else: + return None if isolated_liq: buffer_amount = abs(open_rate - isolated_liq) * self.liquidation_buffer diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 9252040ea..e968b12c2 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -4099,20 +4099,6 @@ def test_get_or_calculate_liquidation_price(mocker, default_conf): ) assert liq_price == 17.540699999999998 - ccxt_exceptionhandlers( - mocker, - default_conf, - api_mock, - "binance", - "get_or_calculate_liquidation_price", - "fetch_positions", - pair="XRP/USDT", - open_rate=0.0, - is_short=False, - position=0.0, - wallet_balance=0.0, - ) - @pytest.mark.parametrize('exchange,rate_start,rate_end,d1,d2,amount,expected_fees', [ ('binance', 0, 2, "2021-09-01 01:00:00", "2021-09-01 04:00:00", 30.0, 0.0), From 09e5fb2f55cf368b8a3126fb1f00be2f8eb1f613 Mon Sep 17 00:00:00 2001 From: rzrymiak <106121613+rzrymiak@users.noreply.github.com> Date: Sat, 30 Jul 2022 22:37:46 +0000 Subject: [PATCH 169/220] Removed description header --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 828a3d1f9..aa446ad54 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ [![Documentation](https://readthedocs.org/projects/freqtrade/badge/)](https://www.freqtrade.io) [![Maintainability](https://api.codeclimate.com/v1/badges/5737e6d668200b7518ff/maintainability)](https://codeclimate.com/github/freqtrade/freqtrade/maintainability) -## Description - Freqtrade is a free and open source crypto trading bot written in Python. It is designed to support all major exchanges and be controlled via Telegram or webUI. It contains backtesting, plotting and money management tools as well as strategy optimization by machine learning. ![freqtrade](https://raw.githubusercontent.com/freqtrade/freqtrade/develop/docs/assets/freqtrade-screenshot.png) From a4bada3ebe5ff927503b067545260ef5fe608c87 Mon Sep 17 00:00:00 2001 From: Kavinkumar <33546454+mkavinkumar1@users.noreply.github.com> Date: Sun, 31 Jul 2022 17:49:04 +0530 Subject: [PATCH 170/220] Partial exit using average price (#6545) Introduce Partial exits --- docs/strategy-callbacks.md | 67 ++- freqtrade/enums/exittype.py | 1 + freqtrade/exchange/exchange.py | 44 +- freqtrade/freqtradebot.py | 194 +++++--- freqtrade/optimize/backtesting.py | 115 +++-- freqtrade/persistence/migrations.py | 10 +- freqtrade/persistence/trade_model.py | 160 +++++-- freqtrade/rpc/rpc.py | 2 +- freqtrade/rpc/telegram.py | 101 +++-- freqtrade/strategy/interface.py | 19 +- .../subtemplates/strategy_methods_advanced.j2 | 26 +- tests/conftest.py | 3 +- tests/exchange/test_exchange.py | 199 ++++++--- .../test_backtesting_adjust_position.py | 86 ++++ tests/rpc/test_rpc.py | 5 +- tests/rpc/test_rpc_telegram.py | 102 ++++- tests/strategy/strats/strategy_test_v3.py | 9 +- tests/test_freqtradebot.py | 414 ++++++++++++++++-- tests/test_integration.py | 59 ++- tests/test_persistence.py | 193 +++++++- 20 files changed, 1462 insertions(+), 347 deletions(-) mode change 100755 => 100644 freqtrade/optimize/backtesting.py diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 59d221bfc..18de3513b 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -629,7 +629,7 @@ class AwesomeStrategy(IStrategy): The `position_adjustment_enable` strategy property enables the usage of `adjust_trade_position()` callback in the strategy. For performance reasons, it's disabled by default and freqtrade will show a warning message on startup if enabled. -`adjust_trade_position()` can be used to perform additional orders, for example to manage risk with DCA (Dollar Cost Averaging). +`adjust_trade_position()` can be used to perform additional orders, for example to manage risk with DCA (Dollar Cost Averaging) or to increase or decrease positions. `max_entry_position_adjustment` property is used to limit the number of additional buys per trade (on top of the first buy) that the bot can execute. By default, the value is -1 which means the bot have no limit on number of adjustment buys. @@ -637,10 +637,13 @@ The strategy is expected to return a stake_amount (in stake currency) between `m If there are not enough funds in the wallet (the return value is above `max_stake`) then the signal will be ignored. Additional orders also result in additional fees and those orders don't count towards `max_open_trades`. -This callback is **not** called when there is an open order (either buy or sell) waiting for execution, or when you have reached the maximum amount of extra buys that you have set on `max_entry_position_adjustment`. +This callback is **not** called when there is an open order (either buy or sell) waiting for execution. + `adjust_trade_position()` is called very frequently for the duration of a trade, so you must keep your implementation as performant as possible. -Position adjustments will always be applied in the direction of the trade, so a positive value will always increase your position, no matter if it's a long or short trade. Modifications to leverage are not possible. +Additional Buys are ignored once you have reached the maximum amount of extra buys that you have set on `max_entry_position_adjustment`, but the callback is called anyway looking for partial exits. + +Position adjustments will always be applied in the direction of the trade, so a positive value will always increase your position (negative values will decrease your position), no matter if it's a long or short trade. Modifications to leverage are not possible. !!! Note "About stake size" Using fixed stake size means it will be the amount used for the first order, just like without position adjustment. @@ -649,12 +652,12 @@ Position adjustments will always be applied in the direction of the trade, so a !!! Warning Stoploss is still calculated from the initial opening price, not averaged price. + Regular stoploss rules still apply (cannot move down). -!!! Warning "/stopbuy" While `/stopbuy` command stops the bot from entering new trades, the position adjustment feature will continue buying new orders on existing trades. !!! Warning "Backtesting" - During backtesting this callback is called for each candle in `timeframe` or `timeframe_detail`, so performance will be affected. + During backtesting this callback is called for each candle in `timeframe` or `timeframe_detail`, so run-time performance will be affected. ``` python from freqtrade.persistence import Trade @@ -675,7 +678,7 @@ class DigDeeperStrategy(IStrategy): max_dca_multiplier = 5.5 # This is called when placing the initial order (opening trade) -def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, + def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, proposed_stake: float, min_stake: Optional[float], max_stake: float, leverage: float, entry_tag: Optional[str], side: str, **kwargs) -> float: @@ -685,22 +688,41 @@ def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: f return proposed_stake / self.max_dca_multiplier def adjust_trade_position(self, trade: Trade, current_time: datetime, - current_rate: float, current_profit: float, min_stake: Optional[float], - max_stake: float, **kwargs): + current_rate: float, current_profit: float, + min_stake: Optional[float], max_stake: float, + current_entry_rate: float, current_exit_rate: float, + current_entry_profit: float, current_exit_profit: float, + **kwargs) -> Optional[float]: """ - Custom trade adjustment logic, returning the stake amount that a trade should be increased. - This means extra buy orders with additional fees. + Custom trade adjustment logic, returning the stake amount that a trade should be + increased or decreased. + This means extra buy or sell orders with additional fees. + Only called when `position_adjustment_enable` is set to True. + + For full documentation please go to https://www.freqtrade.io/en/latest/strategy-advanced/ + + When not implemented by a strategy, returns None :param trade: trade object. :param current_time: datetime object, containing the current datetime :param current_rate: Current buy rate. :param current_profit: Current profit (as ratio), calculated based on current_rate. - :param min_stake: Minimal stake size allowed by exchange. - :param max_stake: Balance available for trading. + :param min_stake: Minimal stake size allowed by exchange (for both entries and exits) + :param max_stake: Maximum stake allowed (either through balance, or by exchange limits). + :param current_entry_rate: Current rate using entry pricing. + :param current_exit_rate: Current rate using exit pricing. + :param current_entry_profit: Current profit using entry pricing. + :param current_exit_profit: Current profit using exit pricing. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - :return float: Stake amount to adjust your trade + :return float: Stake amount to adjust your trade, + Positive values to increase position, Negative values to decrease position. + Return None for no action. """ + if current_profit > 0.05 and trade.nr_of_successful_exits == 0: + # Take half of the profit at +5% + return -(trade.amount / 2) + if current_profit > -0.05: return None @@ -735,6 +757,25 @@ def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: f ``` +### Position adjust calculations + +* Entry rates are calculated using weighted averages. +* Exits will not influence the average entry rate. +* Partial exit relative profit is relative to the average entry price at this point. +* Final exit relative profit is calculated based on the total invested capital. (See example below) + +??? example "Calculation example" + *This example assumes 0 fees for simplicity, and a long position on an imaginary coin.* + + * Buy 100@8\$ + * Buy 100@9\$ -> Avg price: 8.5\$ + * Sell 100@10\$ -> Avg price: 8.5\$, realized profit 150\$, 17.65% + * Buy 150@11\$ -> Avg price: 10\$, realized profit 150\$, 17.65% + * Sell 100@12\$ -> Avg price: 10\$, total realized profit 350\$, 20% + * Sell 150@14\$ -> Avg price: 10\$, total realized profit 950\$, 40% + + The total profit for this trade was 950$ on a 3350$ investment (`100@8$ + 100@9$ + 150@11$`). As such - the final relative profit is 28.35% (`950 / 3350`). + ## Adjust Entry Price The `adjust_entry_price()` callback may be used by strategy developer to refresh/replace limit orders upon arrival of new candles. diff --git a/freqtrade/enums/exittype.py b/freqtrade/enums/exittype.py index 1e15e70cd..b025230ba 100644 --- a/freqtrade/enums/exittype.py +++ b/freqtrade/enums/exittype.py @@ -14,6 +14,7 @@ class ExitType(Enum): FORCE_EXIT = "force_exit" EMERGENCY_EXIT = "emergency_exit" CUSTOM_EXIT = "custom_exit" + PARTIAL_EXIT = "partial_exit" NONE = "" def __str__(self): diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index e180c90b2..b6996211f 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1507,7 +1507,8 @@ class Exchange: return price_side def get_rate(self, pair: str, refresh: bool, - side: EntryExit, is_short: bool) -> float: + side: EntryExit, is_short: bool, + order_book: Optional[dict] = None, ticker: Optional[dict] = None) -> float: """ Calculates bid/ask target bid rate - between current ask price and last price @@ -1539,22 +1540,24 @@ class Exchange: if conf_strategy.get('use_order_book', False): order_book_top = conf_strategy.get('order_book_top', 1) - order_book = self.fetch_l2_order_book(pair, order_book_top) + 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: rate = order_book[f"{price_side}s"][order_book_top - 1][0] except (IndexError, KeyError) as e: logger.warning( - f"{name} Price at location {order_book_top} from orderbook could not be " - f"determined. Orderbook: {order_book}" + 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"{name} price from orderbook {price_side_word}" + logger.debug(f"{pair} - {name} price from orderbook {price_side_word}" f"side - top {order_book_top} order book {side} rate {rate:.8f}") else: logger.debug(f"Using Last {price_side_word} / Last Price") - ticker = self.fetch_ticker(pair) + 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']: @@ -1571,6 +1574,33 @@ class Exchange: return rate + def get_rates(self, pair: str, refresh: bool, is_short: bool) -> Tuple[float, float]: + entry_rate = None + exit_rate = None + if not refresh: + entry_rate = self._entry_rate_cache.get(pair) + exit_rate = self._exit_rate_cache.get(pair) + if entry_rate: + logger.debug(f"Using cached buy rate for {pair}.") + if exit_rate: + logger.debug(f"Using cached sell rate for {pair}.") + + entry_pricing = self._config.get('entry_pricing', {}) + exit_pricing = self._config.get('exit_pricing', {}) + order_book = ticker = None + if not entry_rate and entry_pricing.get('use_order_book', False): + order_book_top = max(entry_pricing.get('order_book_top', 1), + exit_pricing.get('order_book_top', 1)) + order_book = self.fetch_l2_order_book(pair, order_book_top) + entry_rate = self.get_rate(pair, refresh, 'entry', is_short, order_book=order_book) + elif not entry_rate: + ticker = self.fetch_ticker(pair) + entry_rate = self.get_rate(pair, refresh, 'entry', is_short, ticker=ticker) + if not exit_rate: + exit_rate = self.get_rate(pair, refresh, 'exit', + is_short, order_book=order_book, ticker=ticker) + return entry_rate, exit_rate + # Fee handling @retrier @@ -1989,7 +2019,7 @@ class Exchange: else: logger.debug( "Fetching trades for pair %s, since %s %s...", - pair, since, + pair, since, '(' + arrow.get(since // 1000).isoformat() + ') ' if since is not None else '' ) trades = await self._api_async.fetch_trades(pair, since=since, limit=1000) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 50cfb9d7b..757449c8c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -5,6 +5,7 @@ import copy import logging import traceback from datetime import datetime, time, timedelta, timezone +from decimal import Decimal from math import isclose from threading import Lock from typing import Any, Dict, List, Optional, Tuple @@ -525,39 +526,61 @@ class FreqtradeBot(LoggingMixin): If the strategy triggers the adjustment, a new order gets issued. Once that completes, the existing trade is modified to match new data. """ - if self.strategy.max_entry_position_adjustment > -1: - count_of_buys = trade.nr_of_successful_entries - if count_of_buys > self.strategy.max_entry_position_adjustment: - logger.debug(f"Max adjustment entries for {trade.pair} has been reached.") - return - else: - logger.debug("Max adjustment entries is set to unlimited.") - current_rate = self.exchange.get_rate( - trade.pair, side='entry', is_short=trade.is_short, refresh=True) - current_profit = trade.calc_profit_ratio(current_rate) + current_entry_rate, current_exit_rate = self.exchange.get_rates( + trade.pair, True, trade.is_short) - min_stake_amount = self.exchange.get_min_pair_stake_amount(trade.pair, - current_rate, - self.strategy.stoploss) - max_stake_amount = self.exchange.get_max_pair_stake_amount(trade.pair, current_rate) + current_entry_profit = trade.calc_profit_ratio(current_entry_rate) + current_exit_profit = trade.calc_profit_ratio(current_exit_rate) + + min_entry_stake = self.exchange.get_min_pair_stake_amount(trade.pair, + current_entry_rate, + self.strategy.stoploss) + min_exit_stake = self.exchange.get_min_pair_stake_amount(trade.pair, + current_exit_rate, + self.strategy.stoploss) + max_entry_stake = self.exchange.get_max_pair_stake_amount(trade.pair, current_entry_rate) stake_available = self.wallets.get_available_stake_amount() logger.debug(f"Calling adjust_trade_position for pair {trade.pair}") stake_amount = strategy_safe_wrapper(self.strategy.adjust_trade_position, default_retval=None)( - trade=trade, current_time=datetime.now(timezone.utc), current_rate=current_rate, - current_profit=current_profit, min_stake=min_stake_amount, - max_stake=min(max_stake_amount, stake_available)) + trade=trade, + current_time=datetime.now(timezone.utc), current_rate=current_entry_rate, + current_profit=current_entry_profit, min_stake=min_entry_stake, + max_stake=min(max_entry_stake, stake_available), + current_entry_rate=current_entry_rate, current_exit_rate=current_exit_rate, + current_entry_profit=current_entry_profit, current_exit_profit=current_exit_profit + ) if stake_amount is not None and stake_amount > 0.0: # We should increase our position - self.execute_entry(trade.pair, stake_amount, price=current_rate, + if self.strategy.max_entry_position_adjustment > -1: + count_of_entries = trade.nr_of_successful_entries + if count_of_entries > self.strategy.max_entry_position_adjustment: + logger.debug(f"Max adjustment entries for {trade.pair} has been reached.") + return + else: + logger.debug("Max adjustment entries is set to unlimited.") + self.execute_entry(trade.pair, stake_amount, price=current_entry_rate, trade=trade, is_short=trade.is_short) if stake_amount is not None and stake_amount < 0.0: # We should decrease our position - # TODO: Selling part of the trade not implemented yet. - logger.error(f"Unable to decrease trade position / sell partially" - f" for pair {trade.pair}, feature not implemented.") + amount = abs(float(Decimal(stake_amount) / Decimal(current_exit_rate))) + if amount > trade.amount: + # This is currently ineffective as remaining would become < min tradable + # Fixing this would require checking for 0.0 there - + # if we decide that this callback is allowed to "fully exit" + logger.info( + f"Adjusting amount to trade.amount as it is higher. {amount} > {trade.amount}") + amount = trade.amount + + remaining = (trade.amount - amount) * current_exit_rate + if remaining < min_exit_stake: + logger.info(f'Remaining amount of {remaining} would be too small.') + return + + self.execute_trade_exit(trade, current_exit_rate, exit_check=ExitCheckTuple( + exit_type=ExitType.PARTIAL_EXIT), sub_trade_amt=amount) def _check_depth_of_market(self, pair: str, conf: Dict, side: SignalDirection) -> bool: """ @@ -731,7 +754,7 @@ class FreqtradeBot(LoggingMixin): # Updating wallets self.wallets.update() - self._notify_enter(trade, order, order_type) + self._notify_enter(trade, order_obj, order_type, sub_trade=pos_adjust) if pos_adjust: if order_status == 'closed': @@ -740,8 +763,8 @@ class FreqtradeBot(LoggingMixin): else: logger.info(f"DCA order {order_status}, will wait for resolution: {trade}") - # Update fees if order is closed - if order_status == 'closed': + # Update fees if order is non-opened + if order_status in constants.NON_OPEN_EXCHANGE_STATES: self.update_trade_state(trade, order_id, order) return True @@ -830,13 +853,14 @@ class FreqtradeBot(LoggingMixin): return enter_limit_requested, stake_amount, leverage - def _notify_enter(self, trade: Trade, order: Dict, order_type: Optional[str] = None, - fill: bool = False) -> None: + def _notify_enter(self, trade: Trade, order: Order, order_type: Optional[str] = None, + fill: bool = False, sub_trade: bool = False) -> None: """ Sends rpc notification when a entry order occurred. """ msg_type = RPCMessageType.ENTRY_FILL if fill else RPCMessageType.ENTRY - open_rate = safe_value_fallback(order, 'average', 'price') + open_rate = order.safe_price + if open_rate is None: open_rate = trade.open_rate @@ -860,15 +884,17 @@ class FreqtradeBot(LoggingMixin): 'stake_amount': trade.stake_amount, 'stake_currency': self.config['stake_currency'], 'fiat_currency': self.config.get('fiat_display_currency', None), - 'amount': safe_value_fallback(order, 'filled', 'amount') or trade.amount, + 'amount': order.safe_amount_after_fee, 'open_date': trade.open_date or datetime.utcnow(), 'current_rate': current_rate, + 'sub_trade': sub_trade, } # Send the message self.rpc.send_msg(msg) - def _notify_enter_cancel(self, trade: Trade, order_type: str, reason: str) -> None: + def _notify_enter_cancel(self, trade: Trade, order_type: str, reason: str, + sub_trade: bool = False) -> None: """ Sends rpc notification when a entry order cancel occurred. """ @@ -893,6 +919,7 @@ class FreqtradeBot(LoggingMixin): 'open_date': trade.open_date, 'current_rate': current_rate, 'reason': reason, + 'sub_trade': sub_trade, } # Send the message @@ -1366,16 +1393,22 @@ class FreqtradeBot(LoggingMixin): trade.open_order_id = None trade.exit_reason = None cancelled = True + self.wallets.update() else: # TODO: figure out how to handle partially complete sell orders reason = constants.CANCEL_REASON['PARTIALLY_FILLED_KEEP_OPEN'] cancelled = False - self.wallets.update() + order_obj = trade.select_order_by_order_id(order['id']) + if not order_obj: + raise DependencyException( + f"Order_obj not found for {order['id']}. This should not have happened.") + + sub_trade = order_obj.amount != trade.amount self._notify_exit_cancel( trade, order_type=self.strategy.order_types['exit'], - reason=reason + reason=reason, order=order_obj, sub_trade=sub_trade ) return cancelled @@ -1416,6 +1449,7 @@ class FreqtradeBot(LoggingMixin): *, exit_tag: Optional[str] = None, ordertype: Optional[str] = None, + sub_trade_amt: float = None, ) -> bool: """ Executes a trade exit for the given trade and limit @@ -1439,7 +1473,7 @@ class FreqtradeBot(LoggingMixin): # if stoploss is on exchange and we are on dry_run mode, # we consider the sell price stop price if (self.config['dry_run'] and exit_type == 'stoploss' - and self.strategy.order_types['stoploss_on_exchange']): + and self.strategy.order_types['stoploss_on_exchange']): limit = trade.stoploss_or_liquidation # set custom_exit_price if available @@ -1462,15 +1496,17 @@ class FreqtradeBot(LoggingMixin): # Emergency sells (default to market!) order_type = self.strategy.order_types.get("emergency_exit", "market") - amount = self._safe_exit_amount(trade.pair, trade.amount) + amount = self._safe_exit_amount(trade.pair, sub_trade_amt or trade.amount) time_in_force = self.strategy.order_time_in_force['exit'] - if (exit_check.exit_type != ExitType.LIQUIDATION and not strategy_safe_wrapper( - self.strategy.confirm_trade_exit, default_retval=True)( - pair=trade.pair, trade=trade, order_type=order_type, amount=amount, rate=limit, - time_in_force=time_in_force, exit_reason=exit_reason, - sell_reason=exit_reason, # sellreason -> compatibility - current_time=datetime.now(timezone.utc))): + if (exit_check.exit_type != ExitType.LIQUIDATION + and not sub_trade_amt + and not strategy_safe_wrapper( + self.strategy.confirm_trade_exit, default_retval=True)( + pair=trade.pair, trade=trade, order_type=order_type, amount=amount, rate=limit, + time_in_force=time_in_force, exit_reason=exit_reason, + sell_reason=exit_reason, # sellreason -> compatibility + current_time=datetime.now(timezone.utc))): logger.info(f"User denied exit for {trade.pair}.") return False @@ -1504,7 +1540,7 @@ class FreqtradeBot(LoggingMixin): self.strategy.lock_pair(trade.pair, datetime.now(timezone.utc), reason='Auto lock') - self._notify_exit(trade, order_type) + self._notify_exit(trade, order_type, sub_trade=bool(sub_trade_amt), order=order_obj) # In case of market sell orders the order can be closed immediately if order.get('status', 'unknown') in ('closed', 'expired'): self.update_trade_state(trade, trade.open_order_id, order) @@ -1512,16 +1548,27 @@ class FreqtradeBot(LoggingMixin): return True - def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False) -> None: + def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False, + sub_trade: bool = False, order: Order = None) -> None: """ Sends rpc notification when a sell occurred. """ - profit_rate = trade.close_rate if trade.close_rate else trade.close_rate_requested - profit_trade = trade.calc_profit(rate=profit_rate) # Use cached rates here - it was updated seconds ago. current_rate = self.exchange.get_rate( trade.pair, side='exit', is_short=trade.is_short, refresh=False) if not fill else None - profit_ratio = trade.calc_profit_ratio(profit_rate) + + # second condition is for mypy only; order will always be passed during sub trade + if sub_trade and order is not None: + amount = order.safe_filled if fill else order.amount + profit_rate = order.safe_price + + profit = trade.calc_profit(rate=profit_rate, amount=amount, open_rate=trade.open_rate) + profit_ratio = trade.calc_profit_ratio(profit_rate, amount, trade.open_rate) + else: + profit_rate = trade.close_rate if trade.close_rate else trade.close_rate_requested + profit = trade.calc_profit(rate=profit_rate) + trade.realized_profit + profit_ratio = trade.calc_profit_ratio(profit_rate) + amount = trade.amount gain = "profit" if profit_ratio > 0 else "loss" msg = { @@ -1535,11 +1582,11 @@ class FreqtradeBot(LoggingMixin): 'gain': gain, 'limit': profit_rate, 'order_type': order_type, - 'amount': trade.amount, + 'amount': amount, 'open_rate': trade.open_rate, - 'close_rate': trade.close_rate, + 'close_rate': profit_rate, 'current_rate': current_rate, - 'profit_amount': profit_trade, + 'profit_amount': profit, 'profit_ratio': profit_ratio, 'buy_tag': trade.enter_tag, 'enter_tag': trade.enter_tag, @@ -1547,19 +1594,18 @@ class FreqtradeBot(LoggingMixin): 'exit_reason': trade.exit_reason, 'open_date': trade.open_date, 'close_date': trade.close_date or datetime.utcnow(), + 'stake_amount': trade.stake_amount, 'stake_currency': self.config['stake_currency'], 'fiat_currency': self.config.get('fiat_display_currency'), + 'sub_trade': sub_trade, + 'cumulative_profit': trade.realized_profit, } - if 'fiat_display_currency' in self.config: - msg.update({ - 'fiat_currency': self.config['fiat_display_currency'], - }) - # Send the message self.rpc.send_msg(msg) - def _notify_exit_cancel(self, trade: Trade, order_type: str, reason: str) -> None: + def _notify_exit_cancel(self, trade: Trade, order_type: str, reason: str, + order: Order, sub_trade: bool = False) -> None: """ Sends rpc notification when a sell cancel occurred. """ @@ -1585,7 +1631,7 @@ class FreqtradeBot(LoggingMixin): 'gain': gain, 'limit': profit_rate or 0, 'order_type': order_type, - 'amount': trade.amount, + 'amount': order.safe_amount_after_fee, 'open_rate': trade.open_rate, 'current_rate': current_rate, 'profit_amount': profit_trade, @@ -1599,6 +1645,8 @@ class FreqtradeBot(LoggingMixin): 'stake_currency': self.config['stake_currency'], 'fiat_currency': self.config.get('fiat_display_currency', None), 'reason': reason, + 'sub_trade': sub_trade, + 'stake_amount': trade.stake_amount, } if 'fiat_display_currency' in self.config: @@ -1653,14 +1701,18 @@ class FreqtradeBot(LoggingMixin): self.handle_order_fee(trade, order_obj, order) trade.update_trade(order_obj) - # TODO: is the below necessary? it's already done in update_trade for filled buys - trade.recalc_trade_from_orders() Trade.commit() - if order['status'] in constants.NON_OPEN_EXCHANGE_STATES: + if order.get('status') in constants.NON_OPEN_EXCHANGE_STATES: # If a entry order was closed, force update on stoploss on exchange if order.get('side') == trade.entry_side: trade = self.cancel_stoploss_on_exchange(trade) + if not self.edge: + # TODO: should shorting/leverage be supported by Edge, + # then this will need to be fixed. + trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss, initial=True) + if order.get('side') == trade.entry_side or trade.amount > 0: + # Must also run for partial exits # TODO: Margin will need to use interest_rate as well. # interest_rate = self.exchange.get_interest_rate() trade.set_liquidation_price(self.exchange.get_liquidation_price( @@ -1670,24 +1722,30 @@ class FreqtradeBot(LoggingMixin): open_rate=trade.open_rate, is_short=trade.is_short )) - if not self.edge: - # TODO: should shorting/leverage be supported by Edge, - # then this will need to be fixed. - trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss, initial=True) # Updating wallets when order is closed self.wallets.update() - if not trade.is_open: - if send_msg and not stoploss_order and not trade.open_order_id: - self._notify_exit(trade, '', True) - self.handle_protections(trade.pair, trade.trade_direction) - elif send_msg and not trade.open_order_id and not stoploss_order: - # Enter fill - self._notify_enter(trade, order, fill=True) + self.order_close_notify(trade, order_obj, stoploss_order, send_msg) return False + def order_close_notify( + self, trade: Trade, order: Order, stoploss_order: bool, send_msg: bool): + """send "fill" notifications""" + + sub_trade = not isclose(order.safe_amount_after_fee, + trade.amount, abs_tol=constants.MATH_CLOSE_PREC) + if order.ft_order_side == trade.exit_side: + # Exit notification + if send_msg and not stoploss_order and not trade.open_order_id: + self._notify_exit(trade, '', fill=True, sub_trade=sub_trade, order=order) + if not trade.is_open: + self.handle_protections(trade.pair, trade.trade_direction) + elif send_msg and not trade.open_order_id and not stoploss_order: + # Enter fill + self._notify_enter(trade, order, fill=True, sub_trade=sub_trade) + def handle_protections(self, pair: str, side: LongShort) -> None: prot_trig = self.protections.stop_per_pair(pair, side=side) if prot_trig: diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py old mode 100755 new mode 100644 index 2c6cfb0e9..46774e8a5 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -287,8 +287,8 @@ class Backtesting: if unavailable_pairs: raise OperationalException( - f"Pairs {', '.join(unavailable_pairs)} got no leverage tiers available. " - "It is therefore impossible to backtest with this pair at the moment.") + f"Pairs {', '.join(unavailable_pairs)} got no leverage tiers available. " + "It is therefore impossible to backtest with this pair at the moment.") else: self.futures_data = {} @@ -503,16 +503,20 @@ class Backtesting: def _get_adjust_trade_entry_for_candle(self, trade: LocalTrade, row: Tuple ) -> LocalTrade: - current_profit = trade.calc_profit_ratio(row[OPEN_IDX]) - min_stake = self.exchange.get_min_pair_stake_amount(trade.pair, row[OPEN_IDX], -0.1) - max_stake = self.exchange.get_max_pair_stake_amount(trade.pair, row[OPEN_IDX]) + current_rate = row[OPEN_IDX] + current_date = row[DATE_IDX].to_pydatetime() + current_profit = trade.calc_profit_ratio(current_rate) + min_stake = self.exchange.get_min_pair_stake_amount(trade.pair, current_rate, -0.1) + max_stake = self.exchange.get_max_pair_stake_amount(trade.pair, current_rate) stake_available = self.wallets.get_available_stake_amount() stake_amount = strategy_safe_wrapper(self.strategy.adjust_trade_position, default_retval=None)( trade=trade, # type: ignore[arg-type] - current_time=row[DATE_IDX].to_pydatetime(), current_rate=row[OPEN_IDX], + current_time=current_date, current_rate=current_rate, current_profit=current_profit, min_stake=min_stake, - max_stake=min(max_stake, stake_available)) + max_stake=min(max_stake, stake_available), + current_entry_rate=current_rate, current_exit_rate=current_rate, + current_entry_profit=current_profit, current_exit_profit=current_profit) # Check if we should increase our position if stake_amount is not None and stake_amount > 0.0: @@ -523,6 +527,24 @@ class Backtesting: self.wallets.update() return pos_trade + if stake_amount is not None and stake_amount < 0.0: + amount = abs(stake_amount) / current_rate + if amount > trade.amount: + # This is currently ineffective as remaining would become < min tradable + amount = trade.amount + remaining = (trade.amount - amount) * current_rate + if remaining < min_stake: + # Remaining stake is too low to be sold. + return trade + pos_trade = self._exit_trade(trade, row, current_rate, amount) + if pos_trade is not None: + order = pos_trade.orders[-1] + if self._get_order_filled(order.price, row): + order.close_bt_order(current_date, trade) + trade.recalc_trade_from_orders() + self.wallets.update() + return pos_trade + return trade def _get_order_filled(self, rate: float, row: Tuple) -> bool: @@ -602,7 +624,7 @@ class Backtesting: self.strategy.confirm_trade_exit, default_retval=True)( pair=trade.pair, trade=trade, # type: ignore[arg-type] - order_type='limit', + order_type=order_type, amount=trade.amount, rate=close_rate, time_in_force=time_in_force, @@ -613,32 +635,38 @@ class Backtesting: trade.exit_reason = exit_reason - self.order_id_counter += 1 - order = Order( - id=self.order_id_counter, - ft_trade_id=trade.id, - order_date=exit_candle_time, - order_update_date=exit_candle_time, - ft_is_open=True, - ft_pair=trade.pair, - order_id=str(self.order_id_counter), - symbol=trade.pair, - ft_order_side=trade.exit_side, - side=trade.exit_side, - order_type=order_type, - status="open", - price=close_rate, - average=close_rate, - amount=trade.amount, - filled=0, - remaining=trade.amount, - cost=trade.amount * close_rate, - ) - trade.orders.append(order) - return trade - + return self._exit_trade(trade, row, close_rate, trade.amount) return None + def _exit_trade(self, trade: LocalTrade, sell_row: Tuple, + close_rate: float, amount: float = None) -> Optional[LocalTrade]: + self.order_id_counter += 1 + exit_candle_time = sell_row[DATE_IDX].to_pydatetime() + order_type = self.strategy.order_types['exit'] + amount = amount or trade.amount + order = Order( + id=self.order_id_counter, + ft_trade_id=trade.id, + order_date=exit_candle_time, + order_update_date=exit_candle_time, + ft_is_open=True, + ft_pair=trade.pair, + order_id=str(self.order_id_counter), + symbol=trade.pair, + ft_order_side=trade.exit_side, + side=trade.exit_side, + order_type=order_type, + status="open", + price=close_rate, + average=close_rate, + amount=amount, + filled=0, + remaining=amount, + cost=amount * close_rate, + ) + trade.orders.append(order) + return trade + def _get_exit_trade_entry(self, trade: LocalTrade, row: Tuple) -> Optional[LocalTrade]: exit_candle_time: datetime = row[DATE_IDX].to_pydatetime() @@ -865,6 +893,8 @@ class Backtesting: # Ignore trade if entry-order did not fill yet continue exit_row = data[pair][-1] + self._exit_trade(trade, exit_row, exit_row[OPEN_IDX], trade.amount) + trade.orders[-1].close_bt_order(exit_row[DATE_IDX].to_pydatetime(), trade) trade.close_date = exit_row[DATE_IDX].to_pydatetime() trade.exit_reason = ExitType.FORCE_EXIT.value @@ -1006,7 +1036,7 @@ class Backtesting: return None return row - def backtest(self, processed: Dict, + def backtest(self, processed: Dict, # noqa: max-complexity: 13 start_date: datetime, end_date: datetime, max_open_trades: int = 0, position_stacking: bool = False, enable_protections: bool = False) -> Dict[str, Any]: @@ -1108,14 +1138,19 @@ class Backtesting: if order and self._get_order_filled(order.price, row): order.close_bt_order(current_time, trade) trade.open_order_id = None - trade.close_date = current_time - trade.close(order.price, show_msg=False) + sub_trade = order.safe_amount_after_fee != trade.amount + if sub_trade: + order.close_bt_order(current_time, trade) + trade.recalc_trade_from_orders() + else: + trade.close_date = current_time + trade.close(order.price, show_msg=False) - # logger.debug(f"{pair} - Backtesting exit {trade}") - open_trade_count -= 1 - open_trades[pair].remove(trade) - LocalTrade.close_bt_trade(trade) - trades.append(trade) + # logger.debug(f"{pair} - Backtesting exit {trade}") + open_trade_count -= 1 + open_trades[pair].remove(trade) + LocalTrade.close_bt_trade(trade) + trades.append(trade) self.wallets.update() self.run_protections( enable_protections, pair, current_time, trade.trade_direction) diff --git a/freqtrade/persistence/migrations.py b/freqtrade/persistence/migrations.py index 2a8e34cdf..81757a7de 100644 --- a/freqtrade/persistence/migrations.py +++ b/freqtrade/persistence/migrations.py @@ -95,6 +95,7 @@ def migrate_trades_and_orders_table( exit_reason = get_column_def(cols, 'sell_reason', get_column_def(cols, 'exit_reason', 'null')) strategy = get_column_def(cols, 'strategy', 'null') enter_tag = get_column_def(cols, 'buy_tag', get_column_def(cols, 'enter_tag', 'null')) + realized_profit = get_column_def(cols, 'realized_profit', '0.0') trading_mode = get_column_def(cols, 'trading_mode', 'null') @@ -155,7 +156,7 @@ def migrate_trades_and_orders_table( max_rate, min_rate, exit_reason, exit_order_status, strategy, enter_tag, timeframe, open_trade_value, close_profit_abs, trading_mode, leverage, liquidation_price, is_short, - interest_rate, funding_fees + interest_rate, funding_fees, realized_profit ) select id, lower(exchange), pair, {base_currency} base_currency, {stake_currency} stake_currency, @@ -181,7 +182,7 @@ def migrate_trades_and_orders_table( {open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs, {trading_mode} trading_mode, {leverage} leverage, {liquidation_price} liquidation_price, {is_short} is_short, {interest_rate} interest_rate, - {funding_fees} funding_fees + {funding_fees} funding_fees, {realized_profit} realized_profit from {trade_back_name} """)) @@ -297,8 +298,9 @@ def check_migrate(engine, decl_base, previous_tables) -> None: # Check if migration necessary # Migrates both trades and orders table! - if not has_column(cols_orders, 'stop_price'): - # if not has_column(cols_trades, 'base_currency'): + # if ('orders' not in previous_tables + # or not has_column(cols_orders, 'stop_price')): + if not has_column(cols_trades, 'realized_profit'): logger.info(f"Running database migration for trades - " f"backup: {table_back_name}, {order_table_bak_name}") migrate_trades_and_orders_table( diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 44e148a0c..fcb84a59a 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -4,13 +4,15 @@ This module contains the class to persist trades into SQLite import logging from datetime import datetime, timedelta, timezone from decimal import Decimal +from math import isclose from typing import Any, Dict, List, Optional from sqlalchemy import (Boolean, Column, DateTime, Enum, Float, ForeignKey, Integer, String, UniqueConstraint, desc, func) from sqlalchemy.orm import Query, lazyload, relationship -from freqtrade.constants import DATETIME_PRINT_FORMAT, NON_OPEN_EXCHANGE_STATES, BuySell, LongShort +from freqtrade.constants import (DATETIME_PRINT_FORMAT, MATH_CLOSE_PREC, NON_OPEN_EXCHANGE_STATES, + BuySell, LongShort) from freqtrade.enums import ExitType, TradingMode from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.leverage import interest @@ -176,10 +178,9 @@ class Order(_DECL_BASE): self.remaining = 0 self.status = 'closed' self.ft_is_open = False - if (self.ft_order_side == trade.entry_side - and len(trade.select_filled_orders(trade.entry_side)) == 1): + if (self.ft_order_side == trade.entry_side): trade.open_rate = self.price - trade.recalc_open_trade_value() + trade.recalc_trade_from_orders() trade.adjust_stop_loss(trade.open_rate, trade.stop_loss_pct, refresh=True) @staticmethod @@ -237,6 +238,7 @@ class LocalTrade(): trades: List['LocalTrade'] = [] trades_open: List['LocalTrade'] = [] total_profit: float = 0 + realized_profit: float = 0 id: int = 0 @@ -447,6 +449,7 @@ class LocalTrade(): if self.close_date else None), 'close_timestamp': int(self.close_date.replace( tzinfo=timezone.utc).timestamp() * 1000) if self.close_date else None, + 'realized_profit': self.realized_profit or 0.0, 'close_rate': self.close_rate, 'close_rate_requested': self.close_rate_requested, 'close_profit': self.close_profit, # Deprecated @@ -596,14 +599,28 @@ class LocalTrade(): if self.is_open: payment = "SELL" if self.is_short else "BUY" logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.') - self.open_order_id = None + # condition to avoid reset value when updating fees + if self.open_order_id == order.order_id: + self.open_order_id = None + else: + logger.warning( + f'Got different open_order_id {self.open_order_id} != {order.order_id}') self.recalc_trade_from_orders() elif order.ft_order_side == self.exit_side: if self.is_open: payment = "BUY" if self.is_short else "SELL" # * On margin shorts, you buy a little bit more than the amount (amount + interest) logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.') - self.close(order.safe_price) + # condition to avoid reset value when updating fees + if self.open_order_id == order.order_id: + self.open_order_id = None + else: + logger.warning( + f'Got different open_order_id {self.open_order_id} != {order.order_id}') + if isclose(order.safe_amount_after_fee, self.amount, abs_tol=MATH_CLOSE_PREC): + self.close(order.safe_price) + else: + self.recalc_trade_from_orders() elif order.ft_order_side == 'stoploss': self.stoploss_order_id = None self.close_rate_requested = self.stop_loss @@ -622,11 +639,11 @@ class LocalTrade(): """ self.close_rate = rate self.close_date = self.close_date or datetime.utcnow() - self.close_profit = self.calc_profit_ratio(rate) - self.close_profit_abs = self.calc_profit(rate) + self.close_profit_abs = self.calc_profit(rate) + self.realized_profit self.is_open = False self.exit_order_status = 'closed' self.open_order_id = None + self.recalc_trade_from_orders(is_closing=True) if show_msg: logger.info( 'Marking %s as closed as the trade is fulfilled and found no open orders for it.', @@ -672,12 +689,12 @@ class LocalTrade(): """ return len([o for o in self.orders if o.ft_order_side == self.exit_side]) - def _calc_open_trade_value(self) -> float: + def _calc_open_trade_value(self, amount: float, open_rate: float) -> float: """ Calculate the open_rate including open_fee. :return: Price in of the open trade incl. Fees """ - open_trade = Decimal(self.amount) * Decimal(self.open_rate) + open_trade = Decimal(amount) * Decimal(open_rate) fees = open_trade * Decimal(self.fee_open) if self.is_short: return float(open_trade - fees) @@ -689,7 +706,7 @@ class LocalTrade(): Recalculate open_trade_value. Must be called whenever open_rate, fee_open is changed. """ - self.open_trade_value = self._calc_open_trade_value() + self.open_trade_value = self._calc_open_trade_value(self.amount, self.open_rate) def calculate_interest(self) -> Decimal: """ @@ -721,7 +738,7 @@ class LocalTrade(): else: return close_trade - fees - def calc_close_trade_value(self, rate: float) -> float: + def calc_close_trade_value(self, rate: float, amount: float = None) -> float: """ Calculate the Trade's close value including fees :param rate: rate to compare with. @@ -730,96 +747,143 @@ class LocalTrade(): if rate is None and not self.close_rate: return 0.0 - amount = Decimal(self.amount) + amount1 = Decimal(amount or self.amount) trading_mode = self.trading_mode or TradingMode.SPOT if trading_mode == TradingMode.SPOT: - return float(self._calc_base_close(amount, rate, self.fee_close)) + return float(self._calc_base_close(amount1, rate, self.fee_close)) elif (trading_mode == TradingMode.MARGIN): total_interest = self.calculate_interest() if self.is_short: - amount = amount + total_interest - return float(self._calc_base_close(amount, rate, self.fee_close)) + amount1 = amount1 + total_interest + return float(self._calc_base_close(amount1, rate, self.fee_close)) else: # Currency already owned for longs, no need to purchase - return float(self._calc_base_close(amount, rate, self.fee_close) - total_interest) + return float(self._calc_base_close(amount1, rate, self.fee_close) - total_interest) elif (trading_mode == TradingMode.FUTURES): funding_fees = self.funding_fees or 0.0 # Positive funding_fees -> Trade has gained from fees. # Negative funding_fees -> Trade had to pay the fees. if self.is_short: - return float(self._calc_base_close(amount, rate, self.fee_close)) - funding_fees + return float(self._calc_base_close(amount1, rate, self.fee_close)) - funding_fees else: - return float(self._calc_base_close(amount, rate, self.fee_close)) + funding_fees + return float(self._calc_base_close(amount1, rate, self.fee_close)) + funding_fees else: raise OperationalException( f"{self.trading_mode.value} trading is not yet available using freqtrade") - def calc_profit(self, rate: float) -> float: + def calc_profit(self, rate: float, amount: float = None, open_rate: float = None) -> float: """ Calculate the absolute profit in stake currency between Close and Open trade :param rate: close rate to compare with. + :param amount: Amount to use for the calculation. Falls back to trade.amount if not set. + :param open_rate: open_rate to use. Defaults to self.open_rate if not provided. :return: profit in stake currency as float """ - close_trade_value = self.calc_close_trade_value(rate) + close_trade_value = self.calc_close_trade_value(rate, amount) + if amount is None or open_rate is None: + open_trade_value = self.open_trade_value + else: + open_trade_value = self._calc_open_trade_value(amount, open_rate) if self.is_short: - profit = self.open_trade_value - close_trade_value + profit = open_trade_value - close_trade_value else: - profit = close_trade_value - self.open_trade_value + profit = close_trade_value - open_trade_value return float(f"{profit:.8f}") - def calc_profit_ratio(self, rate: float) -> float: + def calc_profit_ratio( + self, rate: float, amount: float = None, open_rate: float = None) -> float: """ Calculates the profit as ratio (including fee). :param rate: rate to compare with. + :param amount: Amount to use for the calculation. Falls back to trade.amount if not set. + :param open_rate: open_rate to use. Defaults to self.open_rate if not provided. :return: profit ratio as float """ - close_trade_value = self.calc_close_trade_value(rate) + close_trade_value = self.calc_close_trade_value(rate, amount) + + if amount is None or open_rate is None: + open_trade_value = self.open_trade_value + else: + open_trade_value = self._calc_open_trade_value(amount, open_rate) short_close_zero = (self.is_short and close_trade_value == 0.0) - long_close_zero = (not self.is_short and self.open_trade_value == 0.0) + long_close_zero = (not self.is_short and open_trade_value == 0.0) leverage = self.leverage or 1.0 if (short_close_zero or long_close_zero): return 0.0 else: if self.is_short: - profit_ratio = (1 - (close_trade_value / self.open_trade_value)) * leverage + profit_ratio = (1 - (close_trade_value / open_trade_value)) * leverage else: - profit_ratio = ((close_trade_value / self.open_trade_value) - 1) * leverage + profit_ratio = ((close_trade_value / open_trade_value) - 1) * leverage return float(f"{profit_ratio:.8f}") - def recalc_trade_from_orders(self): + def recalc_trade_from_orders(self, is_closing: bool = False): + + current_amount = 0.0 + current_stake = 0.0 + total_stake = 0.0 # Total stake after all buy orders (does not subtract!) + avg_price = 0.0 + close_profit = 0.0 + close_profit_abs = 0.0 - total_amount = 0.0 - total_stake = 0.0 for o in self.orders: - if (o.ft_is_open or - (o.ft_order_side != self.entry_side) or - (o.status not in NON_OPEN_EXCHANGE_STATES)): + if o.ft_is_open or not o.filled: continue tmp_amount = o.safe_amount_after_fee - tmp_price = o.average or o.price - if tmp_amount > 0.0 and tmp_price is not None: - total_amount += tmp_amount - total_stake += tmp_price * tmp_amount + tmp_price = o.safe_price - if total_amount > 0: + is_exit = o.ft_order_side != self.entry_side + side = -1 if is_exit else 1 + if tmp_amount > 0.0 and tmp_price is not None: + current_amount += tmp_amount * side + price = avg_price if is_exit else tmp_price + current_stake += price * tmp_amount * side + + if current_amount > 0: + avg_price = current_stake / current_amount + + if is_exit: + # Process partial exits + exit_rate = o.safe_price + exit_amount = o.safe_amount_after_fee + profit = self.calc_profit(rate=exit_rate, amount=exit_amount, open_rate=avg_price) + close_profit_abs += profit + close_profit = self.calc_profit_ratio( + exit_rate, amount=exit_amount, open_rate=avg_price) + if current_amount <= 0: + profit = close_profit_abs + else: + total_stake = total_stake + self._calc_open_trade_value(tmp_amount, price) + + if close_profit: + self.close_profit = close_profit + self.realized_profit = close_profit_abs + self.close_profit_abs = profit + + if current_amount > 0: + # Trade is still open # Leverage not updated, as we don't allow changing leverage through DCA at the moment. - self.open_rate = total_stake / total_amount - self.stake_amount = total_stake / (self.leverage or 1.0) - self.amount = total_amount - self.fee_open_cost = self.fee_open * total_stake + self.open_rate = current_stake / current_amount + self.stake_amount = current_stake / (self.leverage or 1.0) + self.amount = current_amount + self.fee_open_cost = self.fee_open * current_stake self.recalc_open_trade_value() if self.stop_loss_pct is not None and self.open_rate is not None: self.adjust_stop_loss(self.open_rate, self.stop_loss_pct) + elif is_closing and total_stake > 0: + # Close profit abs / maximum owned + # Fees are considered as they are part of close_profit_abs + self.close_profit = (close_profit_abs / total_stake) * self.leverage def select_order_by_order_id(self, order_id: str) -> Optional[Order]: """ @@ -841,7 +905,7 @@ class LocalTrade(): """ orders = self.orders if order_side: - orders = [o for o in self.orders if o.ft_order_side == order_side] + orders = [o for o in orders if o.ft_order_side == order_side] if is_open is not None: orders = [o for o in orders if o.ft_is_open == is_open] if len(orders) > 0: @@ -856,9 +920,9 @@ class LocalTrade(): :return: array of Order objects """ return [o for o in self.orders if ((o.ft_order_side == order_side) or (order_side is None)) - and o.ft_is_open is False and - (o.filled or 0) > 0 and - o.status in NON_OPEN_EXCHANGE_STATES] + and o.ft_is_open is False + and o.filled + and o.status in NON_OPEN_EXCHANGE_STATES] def select_filled_or_open_orders(self) -> List['Order']: """ @@ -1023,6 +1087,7 @@ class Trade(_DECL_BASE, LocalTrade): open_trade_value = Column(Float) close_rate: Optional[float] = Column(Float) close_rate_requested = Column(Float) + realized_profit = Column(Float, default=0.0) close_profit = Column(Float) close_profit_abs = Column(Float) stake_amount = Column(Float, nullable=False) @@ -1068,6 +1133,7 @@ class Trade(_DECL_BASE, LocalTrade): def __init__(self, **kwargs): super().__init__(**kwargs) + self.realized_profit = 0 self.recalc_open_trade_value() def delete(self) -> None: diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index e6948c9e2..9d6696803 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -201,7 +201,7 @@ class RPC: trade_dict = trade.to_json() trade_dict.update(dict( - close_profit=trade.close_profit if trade.close_profit is not None else None, + close_profit=trade.close_profit if not trade.is_open else None, current_rate=current_rate, current_profit=current_profit, # Deprecated current_profit_pct=round(current_profit * 100, 2), # Deprecated diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 121324d90..66192fb16 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -274,7 +274,7 @@ class Telegram(RPCHandler): f"{emoji} *{self._exchange_from_msg(msg)}:*" f" {entry_side['entered'] if is_fill else entry_side['enter']} {msg['pair']}" f" (#{msg['trade_id']})\n" - ) + ) message += self._add_analyzed_candle(msg['pair']) message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else "" message += f"*Amount:* `{msg['amount']:.8f}`\n" @@ -315,20 +315,36 @@ class Telegram(RPCHandler): msg['profit_fiat'] = self._rpc._fiat_converter.convert_amount( msg['profit_amount'], msg['stake_currency'], msg['fiat_currency']) msg['profit_extra'] = ( - f" ({msg['gain']}: {msg['profit_amount']:.8f} {msg['stake_currency']}" - f" / {msg['profit_fiat']:.3f} {msg['fiat_currency']})") + f" / {msg['profit_fiat']:.3f} {msg['fiat_currency']}") else: msg['profit_extra'] = '' + msg['profit_extra'] = ( + f" ({msg['gain']}: {msg['profit_amount']:.8f} {msg['stake_currency']}" + f"{msg['profit_extra']})") is_fill = msg['type'] == RPCMessageType.EXIT_FILL + is_sub_trade = msg.get('sub_trade') + is_sub_profit = msg['profit_amount'] != msg.get('cumulative_profit') + profit_prefix = ('Sub ' if is_sub_profit + else 'Cumulative ') if is_sub_trade else '' + cp_extra = '' + if is_sub_profit and is_sub_trade: + if self._rpc._fiat_converter: + cp_fiat = self._rpc._fiat_converter.convert_amount( + msg['cumulative_profit'], msg['stake_currency'], msg['fiat_currency']) + cp_extra = f" / {cp_fiat:.3f} {msg['fiat_currency']}" + else: + cp_extra = '' + cp_extra = f"*Cumulative Profit:* (`{msg['cumulative_profit']:.8f} " \ + f"{msg['stake_currency']}{cp_extra}`)\n" message = ( f"{msg['emoji']} *{self._exchange_from_msg(msg)}:* " f"{'Exited' if is_fill else 'Exiting'} {msg['pair']} (#{msg['trade_id']})\n" f"{self._add_analyzed_candle(msg['pair'])}" - f"*{'Profit' if is_fill else 'Unrealized Profit'}:* " + f"*{f'{profit_prefix}Profit' if is_fill else f'Unrealized {profit_prefix}Profit'}:* " f"`{msg['profit_ratio']:.2%}{msg['profit_extra']}`\n" + f"{cp_extra}" f"*Enter Tag:* `{msg['enter_tag']}`\n" f"*Exit Reason:* `{msg['exit_reason']}`\n" - f"*Duration:* `{msg['duration']} ({msg['duration_min']:.1f} min)`\n" f"*Direction:* `{msg['direction']}`\n" f"{msg['leverage_text']}" f"*Amount:* `{msg['amount']:.8f}`\n" @@ -336,11 +352,25 @@ class Telegram(RPCHandler): ) if msg['type'] == RPCMessageType.EXIT: message += (f"*Current Rate:* `{msg['current_rate']:.8f}`\n" - f"*Close Rate:* `{msg['limit']:.8f}`") + f"*Exit Rate:* `{msg['limit']:.8f}`") elif msg['type'] == RPCMessageType.EXIT_FILL: - message += f"*Close Rate:* `{msg['close_rate']:.8f}`" + message += f"*Exit Rate:* `{msg['close_rate']:.8f}`" + if msg.get('sub_trade'): + if self._rpc._fiat_converter: + msg['stake_amount_fiat'] = self._rpc._fiat_converter.convert_amount( + msg['stake_amount'], msg['stake_currency'], msg['fiat_currency']) + else: + msg['stake_amount_fiat'] = 0 + rem = round_coin_value(msg['stake_amount'], msg['stake_currency']) + message += f"\n*Remaining:* `({rem}" + if msg.get('fiat_currency', None): + message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}" + + message += ")`" + else: + message += f"\n*Duration:* `{msg['duration']} ({msg['duration_min']:.1f} min)`" return message def compose_message(self, msg: Dict[str, Any], msg_type: RPCMessageType) -> str: @@ -353,7 +383,8 @@ class Telegram(RPCHandler): elif msg_type in (RPCMessageType.ENTRY_CANCEL, RPCMessageType.EXIT_CANCEL): msg['message_side'] = 'enter' if msg_type in [RPCMessageType.ENTRY_CANCEL] else 'exit' message = (f"\N{WARNING SIGN} *{self._exchange_from_msg(msg)}:* " - f"Cancelling {msg['message_side']} Order for {msg['pair']} " + f"Cancelling {'partial ' if msg.get('sub_trade') else ''}" + f"{msg['message_side']} Order for {msg['pair']} " f"(#{msg['trade_id']}). Reason: {msg['reason']}.") elif msg_type == RPCMessageType.PROTECTION_TRIGGER: @@ -424,7 +455,7 @@ class Telegram(RPCHandler): else: return "\N{CROSS MARK}" - def _prepare_entry_details(self, filled_orders: List, quote_currency: str, is_open: bool): + def _prepare_order_details(self, filled_orders: List, quote_currency: str, is_open: bool): """ Prepare details of trade with entry adjustment enabled """ @@ -433,44 +464,51 @@ class Telegram(RPCHandler): first_avg = filled_orders[0]["safe_price"] for x, order in enumerate(filled_orders): - if not order['ft_is_entry'] or order['is_open'] is True: + if order['is_open'] is True: continue + wording = 'Entry' if order['ft_is_entry'] else 'Exit' + cur_entry_datetime = arrow.get(order["order_filled_date"]) - cur_entry_amount = order["amount"] + cur_entry_amount = order["filled"] or order["amount"] cur_entry_average = order["safe_price"] lines.append(" ") if x == 0: - lines.append(f"*Entry #{x+1}:*") + lines.append(f"*{wording} #{x+1}:*") lines.append( - f"*Entry Amount:* {cur_entry_amount} ({order['cost']:.8f} {quote_currency})") - lines.append(f"*Average Entry Price:* {cur_entry_average}") + f"*Amount:* {cur_entry_amount} ({order['cost']:.8f} {quote_currency})") + lines.append(f"*Average Price:* {cur_entry_average}") else: sumA = 0 sumB = 0 for y in range(x): - sumA += (filled_orders[y]["amount"] * filled_orders[y]["safe_price"]) - sumB += filled_orders[y]["amount"] + amount = filled_orders[y]["filled"] or filled_orders[y]["amount"] + sumA += amount * filled_orders[y]["safe_price"] + sumB += amount prev_avg_price = sumA / sumB + # TODO: This calculation ignores fees. price_to_1st_entry = ((cur_entry_average - first_avg) / first_avg) minus_on_entry = 0 if prev_avg_price: minus_on_entry = (cur_entry_average - prev_avg_price) / prev_avg_price - dur_entry = cur_entry_datetime - arrow.get( - filled_orders[x - 1]["order_filled_date"]) - days = dur_entry.days - hours, remainder = divmod(dur_entry.seconds, 3600) - minutes, seconds = divmod(remainder, 60) - lines.append(f"*Entry #{x+1}:* at {minus_on_entry:.2%} avg profit") + lines.append(f"*{wording} #{x+1}:* at {minus_on_entry:.2%} avg profit") if is_open: lines.append("({})".format(cur_entry_datetime .humanize(granularity=["day", "hour", "minute"]))) lines.append( - f"*Entry Amount:* {cur_entry_amount} ({order['cost']:.8f} {quote_currency})") - lines.append(f"*Average Entry Price:* {cur_entry_average} " + f"*Amount:* {cur_entry_amount} ({order['cost']:.8f} {quote_currency})") + lines.append(f"*Average {wording} Price:* {cur_entry_average} " f"({price_to_1st_entry:.2%} from 1st entry rate)") - lines.append(f"*Order filled at:* {order['order_filled_date']}") - lines.append(f"({days}d {hours}h {minutes}m {seconds}s from previous entry)") + lines.append(f"*Order filled:* {order['order_filled_date']}") + + # TODO: is this really useful? + # dur_entry = cur_entry_datetime - arrow.get( + # filled_orders[x - 1]["order_filled_date"]) + # days = dur_entry.days + # hours, remainder = divmod(dur_entry.seconds, 3600) + # minutes, seconds = divmod(remainder, 60) + # lines.append( + # f"({days}d {hours}h {minutes}m {seconds}s from previous {wording.lower()})") return lines @authorized_only @@ -486,7 +524,14 @@ class Telegram(RPCHandler): if context.args and 'table' in context.args: self._status_table(update, context) return + else: + self._status_msg(update, context) + def _status_msg(self, update: Update, context: CallbackContext) -> None: + """ + handler for `/status` and `/status `. + + """ try: # Check if there's at least one numerical ID provided. @@ -529,6 +574,8 @@ class Telegram(RPCHandler): ]) if r['is_open']: + if r.get('realized_profit'): + lines.append("*Realized Profit:* `{realized_profit:.8f}`") if (r['stop_loss_abs'] != r['initial_stop_loss_abs'] and r['initial_stop_loss_ratio'] is not None): # Adding initial stoploss only if it is different from stoploss @@ -546,7 +593,7 @@ class Telegram(RPCHandler): else: lines.append("*Open Order:* `{open_order}`") - lines_detail = self._prepare_entry_details( + lines_detail = self._prepare_order_details( r['orders'], r['quote_currency'], r['is_open']) lines.extend(lines_detail if lines_detail else "") diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 824f31258..5e0aba2fe 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -463,10 +463,13 @@ class IStrategy(ABC, HyperStrategyMixin): def adjust_trade_position(self, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, min_stake: Optional[float], max_stake: float, + current_entry_rate: float, current_exit_rate: float, + current_entry_profit: float, current_exit_profit: float, **kwargs) -> Optional[float]: """ - Custom trade adjustment logic, returning the stake amount that a trade should be increased. - This means extra buy orders with additional fees. + Custom trade adjustment logic, returning the stake amount that a trade should be + increased or decreased. + This means extra buy or sell orders with additional fees. Only called when `position_adjustment_enable` is set to True. For full documentation please go to https://www.freqtrade.io/en/latest/strategy-advanced/ @@ -477,10 +480,16 @@ class IStrategy(ABC, HyperStrategyMixin): :param current_time: datetime object, containing the current datetime :param current_rate: Current buy rate. :param current_profit: Current profit (as ratio), calculated based on current_rate. - :param min_stake: Minimal stake size allowed by exchange. - :param max_stake: Balance available for trading. + :param min_stake: Minimal stake size allowed by exchange (for both entries and exits) + :param max_stake: Maximum stake allowed (either through balance, or by exchange limits). + :param current_entry_rate: Current rate using entry pricing. + :param current_exit_rate: Current rate using exit pricing. + :param current_entry_profit: Current profit using entry pricing. + :param current_exit_profit: Current profit using exit pricing. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - :return float: Stake amount to adjust your trade + :return float: Stake amount to adjust your trade, + Positive values to increase position, Negative values to decrease position. + Return None for no action. """ return None diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index 989f1d37a..488ca2fd7 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -247,12 +247,16 @@ def check_exit_timeout(self, pair: str, trade: 'Trade', order: 'Order', """ return False -def adjust_trade_position(self, trade: 'Trade', current_time: 'datetime', - current_rate: float, current_profit: float, min_stake: Optional[float], - max_stake: float, **kwargs) -> 'Optional[float]': +def adjust_trade_position(self, trade: 'Trade', current_time: datetime, + current_rate: float, current_profit: float, + min_stake: Optional[float], max_stake: float, + current_entry_rate: float, current_exit_rate: float, + current_entry_profit: float, current_exit_profit: float, + **kwargs) -> Optional[float]: """ - Custom trade adjustment logic, returning the stake amount that a trade should be increased. - This means extra buy orders with additional fees. + Custom trade adjustment logic, returning the stake amount that a trade should be + increased or decreased. + This means extra buy or sell orders with additional fees. Only called when `position_adjustment_enable` is set to True. For full documentation please go to https://www.freqtrade.io/en/latest/strategy-advanced/ @@ -263,10 +267,16 @@ def adjust_trade_position(self, trade: 'Trade', current_time: 'datetime', :param current_time: datetime object, containing the current datetime :param current_rate: Current buy rate. :param current_profit: Current profit (as ratio), calculated based on current_rate. - :param min_stake: Minimal stake size allowed by exchange. - :param max_stake: Balance available for trading. + :param min_stake: Minimal stake size allowed by exchange (for both entries and exits) + :param max_stake: Maximum stake allowed (either through balance, or by exchange limits). + :param current_entry_rate: Current rate using entry pricing. + :param current_exit_rate: Current rate using exit pricing. + :param current_entry_profit: Current profit using entry pricing. + :param current_exit_profit: Current profit using exit pricing. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - :return float: Stake amount to adjust your trade + :return float: Stake amount to adjust your trade, + Positive values to increase position, Negative values to decrease position. + Return None for no action. """ return None diff --git a/tests/conftest.py b/tests/conftest.py index ff3e1007f..a02fc4566 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1627,8 +1627,8 @@ def limit_buy_order_open(): 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 0.00001099, + 'average': 0.00001099, 'amount': 90.99181073, - 'average': None, 'filled': 0.0, 'cost': 0.0009999, 'remaining': 90.99181073, @@ -2817,6 +2817,7 @@ def limit_buy_order_usdt_open(): 'datetime': arrow.utcnow().isoformat(), 'timestamp': arrow.utcnow().int_timestamp * 1000, 'price': 2.00, + 'average': 2.00, 'amount': 30.0, 'filled': 0.0, 'cost': 60.0, diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index e968b12c2..d73e26683 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -27,6 +27,57 @@ from tests.conftest import get_mock_coro, get_patched_exchange, log_has, log_has # Make sure to always keep one exchange here which is NOT subclassed!! EXCHANGES = ['bittrex', 'binance', 'kraken', 'ftx', 'gateio'] +get_entry_rate_data = [ + ('other', 20, 19, 10, 0.0, 20), # Full ask side + ('ask', 20, 19, 10, 0.0, 20), # Full ask side + ('ask', 20, 19, 10, 1.0, 10), # Full last side + ('ask', 20, 19, 10, 0.5, 15), # Between ask and last + ('ask', 20, 19, 10, 0.7, 13), # Between ask and last + ('ask', 20, 19, 10, 0.3, 17), # Between ask and last + ('ask', 5, 6, 10, 1.0, 5), # last bigger than ask + ('ask', 5, 6, 10, 0.5, 5), # last bigger than ask + ('ask', 20, 19, 10, None, 20), # price_last_balance missing + ('ask', 10, 20, None, 0.5, 10), # last not available - uses ask + ('ask', 4, 5, None, 0.5, 4), # last not available - uses ask + ('ask', 4, 5, None, 1, 4), # last not available - uses ask + ('ask', 4, 5, None, 0, 4), # last not available - uses ask + ('same', 21, 20, 10, 0.0, 20), # Full bid side + ('bid', 21, 20, 10, 0.0, 20), # Full bid side + ('bid', 21, 20, 10, 1.0, 10), # Full last side + ('bid', 21, 20, 10, 0.5, 15), # Between bid and last + ('bid', 21, 20, 10, 0.7, 13), # Between bid and last + ('bid', 21, 20, 10, 0.3, 17), # Between bid and last + ('bid', 6, 5, 10, 1.0, 5), # last bigger than bid + ('bid', 21, 20, 10, None, 20), # price_last_balance missing + ('bid', 6, 5, 10, 0.5, 5), # last bigger than bid + ('bid', 21, 20, None, 0.5, 20), # last not available - uses bid + ('bid', 6, 5, None, 0.5, 5), # last not available - uses bid + ('bid', 6, 5, None, 1, 5), # last not available - uses bid + ('bid', 6, 5, None, 0, 5), # last not available - uses bid +] + +get_sell_rate_data = [ + ('bid', 12.0, 11.0, 11.5, 0.0, 11.0), # full bid side + ('bid', 12.0, 11.0, 11.5, 1.0, 11.5), # full last side + ('bid', 12.0, 11.0, 11.5, 0.5, 11.25), # between bid and lat + ('bid', 12.0, 11.2, 10.5, 0.0, 11.2), # Last smaller than bid + ('bid', 12.0, 11.2, 10.5, 1.0, 11.2), # Last smaller than bid - uses bid + ('bid', 12.0, 11.2, 10.5, 0.5, 11.2), # Last smaller than bid - uses bid + ('bid', 0.003, 0.002, 0.005, 0.0, 0.002), + ('bid', 0.003, 0.002, 0.005, None, 0.002), + ('ask', 12.0, 11.0, 12.5, 0.0, 12.0), # full ask side + ('ask', 12.0, 11.0, 12.5, 1.0, 12.5), # full last side + ('ask', 12.0, 11.0, 12.5, 0.5, 12.25), # between bid and lat + ('ask', 12.2, 11.2, 10.5, 0.0, 12.2), # Last smaller than ask + ('ask', 12.0, 11.0, 10.5, 1.0, 12.0), # Last smaller than ask - uses ask + ('ask', 12.0, 11.2, 10.5, 0.5, 12.0), # Last smaller than ask - uses ask + ('ask', 10.0, 11.0, 11.0, 0.0, 10.0), + ('ask', 10.11, 11.2, 11.0, 0.0, 10.11), + ('ask', 0.001, 0.002, 11.0, 0.0, 0.001), + ('ask', 0.006, 1.0, 11.0, 0.0, 0.006), + ('ask', 0.006, 1.0, 11.0, None, 0.006), +] + def ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name, fun, mock_ccxt_fun, retries=API_RETRY_COUNT + 1, **kwargs): @@ -2360,34 +2411,7 @@ def test_fetch_l2_order_book_exception(default_conf, mocker, exchange_name): exchange.fetch_l2_order_book(pair='ETH/BTC', limit=50) -@pytest.mark.parametrize("side,ask,bid,last,last_ab,expected", [ - ('other', 20, 19, 10, 0.0, 20), # Full ask side - ('ask', 20, 19, 10, 0.0, 20), # Full ask side - ('ask', 20, 19, 10, 1.0, 10), # Full last side - ('ask', 20, 19, 10, 0.5, 15), # Between ask and last - ('ask', 20, 19, 10, 0.7, 13), # Between ask and last - ('ask', 20, 19, 10, 0.3, 17), # Between ask and last - ('ask', 5, 6, 10, 1.0, 5), # last bigger than ask - ('ask', 5, 6, 10, 0.5, 5), # last bigger than ask - ('ask', 20, 19, 10, None, 20), # price_last_balance missing - ('ask', 10, 20, None, 0.5, 10), # last not available - uses ask - ('ask', 4, 5, None, 0.5, 4), # last not available - uses ask - ('ask', 4, 5, None, 1, 4), # last not available - uses ask - ('ask', 4, 5, None, 0, 4), # last not available - uses ask - ('same', 21, 20, 10, 0.0, 20), # Full bid side - ('bid', 21, 20, 10, 0.0, 20), # Full bid side - ('bid', 21, 20, 10, 1.0, 10), # Full last side - ('bid', 21, 20, 10, 0.5, 15), # Between bid and last - ('bid', 21, 20, 10, 0.7, 13), # Between bid and last - ('bid', 21, 20, 10, 0.3, 17), # Between bid and last - ('bid', 6, 5, 10, 1.0, 5), # last bigger than bid - ('bid', 21, 20, 10, None, 20), # price_last_balance missing - ('bid', 6, 5, 10, 0.5, 5), # last bigger than bid - ('bid', 21, 20, None, 0.5, 20), # last not available - uses bid - ('bid', 6, 5, None, 0.5, 5), # last not available - uses bid - ('bid', 6, 5, None, 1, 5), # last not available - uses bid - ('bid', 6, 5, None, 0, 5), # last not available - uses bid -]) +@pytest.mark.parametrize("side,ask,bid,last,last_ab,expected", get_entry_rate_data) def test_get_entry_rate(mocker, default_conf, caplog, side, ask, bid, last, last_ab, expected) -> None: caplog.set_level(logging.DEBUG) @@ -2411,27 +2435,7 @@ def test_get_entry_rate(mocker, default_conf, caplog, side, ask, bid, assert not log_has("Using cached entry rate for ETH/BTC.", caplog) -@pytest.mark.parametrize('side,ask,bid,last,last_ab,expected', [ - ('bid', 12.0, 11.0, 11.5, 0.0, 11.0), # full bid side - ('bid', 12.0, 11.0, 11.5, 1.0, 11.5), # full last side - ('bid', 12.0, 11.0, 11.5, 0.5, 11.25), # between bid and lat - ('bid', 12.0, 11.2, 10.5, 0.0, 11.2), # Last smaller than bid - ('bid', 12.0, 11.2, 10.5, 1.0, 11.2), # Last smaller than bid - uses bid - ('bid', 12.0, 11.2, 10.5, 0.5, 11.2), # Last smaller than bid - uses bid - ('bid', 0.003, 0.002, 0.005, 0.0, 0.002), - ('bid', 0.003, 0.002, 0.005, None, 0.002), - ('ask', 12.0, 11.0, 12.5, 0.0, 12.0), # full ask side - ('ask', 12.0, 11.0, 12.5, 1.0, 12.5), # full last side - ('ask', 12.0, 11.0, 12.5, 0.5, 12.25), # between bid and lat - ('ask', 12.2, 11.2, 10.5, 0.0, 12.2), # Last smaller than ask - ('ask', 12.0, 11.0, 10.5, 1.0, 12.0), # Last smaller than ask - uses ask - ('ask', 12.0, 11.2, 10.5, 0.5, 12.0), # Last smaller than ask - uses ask - ('ask', 10.0, 11.0, 11.0, 0.0, 10.0), - ('ask', 10.11, 11.2, 11.0, 0.0, 10.11), - ('ask', 0.001, 0.002, 11.0, 0.0, 0.001), - ('ask', 0.006, 1.0, 11.0, 0.0, 0.006), - ('ask', 0.006, 1.0, 11.0, None, 0.006), -]) +@pytest.mark.parametrize('side,ask,bid,last,last_ab,expected', get_sell_rate_data) def test_get_exit_rate(default_conf, mocker, caplog, side, bid, ask, last, last_ab, expected) -> None: caplog.set_level(logging.DEBUG) @@ -2481,14 +2485,14 @@ def test_get_ticker_rate_error(mocker, entry, default_conf, caplog, side, is_sho @pytest.mark.parametrize('is_short,side,expected', [ - (False, 'bid', 0.043936), # Value from order_book_l2 fitxure - bids side - (False, 'ask', 0.043949), # Value from order_book_l2 fitxure - asks side - (False, 'other', 0.043936), # Value from order_book_l2 fitxure - bids side - (False, 'same', 0.043949), # Value from order_book_l2 fitxure - asks side - (True, 'bid', 0.043936), # Value from order_book_l2 fitxure - bids side - (True, 'ask', 0.043949), # Value from order_book_l2 fitxure - asks side - (True, 'other', 0.043949), # Value from order_book_l2 fitxure - asks side - (True, 'same', 0.043936), # Value from order_book_l2 fitxure - bids side + (False, 'bid', 0.043936), # Value from order_book_l2 fixture - bids side + (False, 'ask', 0.043949), # Value from order_book_l2 fixture - asks side + (False, 'other', 0.043936), # Value from order_book_l2 fixture - bids side + (False, 'same', 0.043949), # Value from order_book_l2 fixture - asks side + (True, 'bid', 0.043936), # Value from order_book_l2 fixture - bids side + (True, 'ask', 0.043949), # Value from order_book_l2 fixture - asks side + (True, 'other', 0.043949), # Value from order_book_l2 fixture - asks side + (True, 'same', 0.043936), # Value from order_book_l2 fixture - bids side ]) def test_get_exit_rate_orderbook( default_conf, mocker, caplog, is_short, side, expected, order_book_l2): @@ -2521,7 +2525,8 @@ def test_get_exit_rate_orderbook_exception(default_conf, mocker, caplog): exchange = get_patched_exchange(mocker, default_conf) with pytest.raises(PricingError): exchange.get_rate(pair, refresh=True, side="exit", is_short=False) - assert log_has_re(r"Exit Price at location 1 from orderbook could not be determined\..*", + assert log_has_re(rf"{pair} - Exit Price at location 1 from orderbook " + rf"could not be determined\..*", caplog) @@ -2548,6 +2553,84 @@ def test_get_exit_rate_exception(default_conf, mocker, is_short): assert exchange.get_rate(pair, refresh=True, side="exit", is_short=is_short) == 0.13 +@pytest.mark.parametrize("side,ask,bid,last,last_ab,expected", get_entry_rate_data) +@pytest.mark.parametrize("side2", ['bid', 'ask']) +@pytest.mark.parametrize("use_order_book", [True, False]) +def test_get_rates_testing_buy(mocker, default_conf, caplog, side, ask, bid, + last, last_ab, expected, + side2, use_order_book, order_book_l2) -> None: + caplog.set_level(logging.DEBUG) + if last_ab is None: + del default_conf['entry_pricing']['price_last_balance'] + else: + default_conf['entry_pricing']['price_last_balance'] = last_ab + default_conf['entry_pricing']['price_side'] = side + default_conf['exit_pricing']['price_side'] = side2 + default_conf['exit_pricing']['use_order_book'] = use_order_book + api_mock = MagicMock() + api_mock.fetch_l2_order_book = order_book_l2 + api_mock.fetch_ticker = MagicMock( + return_value={'ask': ask, 'last': last, 'bid': bid}) + exchange = get_patched_exchange(mocker, default_conf, api_mock) + + assert exchange.get_rates('ETH/BTC', refresh=True, is_short=False)[0] == expected + assert not log_has("Using cached buy rate for ETH/BTC.", caplog) + + api_mock.fetch_l2_order_book.reset_mock() + api_mock.fetch_ticker.reset_mock() + assert exchange.get_rates('ETH/BTC', refresh=False, is_short=False)[0] == expected + assert log_has("Using cached buy rate for ETH/BTC.", caplog) + assert api_mock.fetch_l2_order_book.call_count == 0 + assert api_mock.fetch_ticker.call_count == 0 + # Running a 2nd time with Refresh on! + caplog.clear() + + assert exchange.get_rates('ETH/BTC', refresh=True, is_short=False)[0] == expected + assert not log_has("Using cached buy rate for ETH/BTC.", caplog) + + assert api_mock.fetch_l2_order_book.call_count == int(use_order_book) + assert api_mock.fetch_ticker.call_count == 1 + + +@pytest.mark.parametrize('side,ask,bid,last,last_ab,expected', get_sell_rate_data) +@pytest.mark.parametrize("side2", ['bid', 'ask']) +@pytest.mark.parametrize("use_order_book", [True, False]) +def test_get_rates_testing_sell(default_conf, mocker, caplog, side, bid, ask, + last, last_ab, expected, + side2, use_order_book, order_book_l2) -> None: + caplog.set_level(logging.DEBUG) + + default_conf['exit_pricing']['price_side'] = side + if last_ab is not None: + default_conf['exit_pricing']['price_last_balance'] = last_ab + + default_conf['entry_pricing']['price_side'] = side2 + default_conf['entry_pricing']['use_order_book'] = use_order_book + api_mock = MagicMock() + api_mock.fetch_l2_order_book = order_book_l2 + api_mock.fetch_ticker = MagicMock( + return_value={'ask': ask, 'last': last, 'bid': bid}) + exchange = get_patched_exchange(mocker, default_conf, api_mock) + + pair = "ETH/BTC" + + # Test regular mode + rate = exchange.get_rates(pair, refresh=True, is_short=False)[1] + assert not log_has("Using cached sell rate for ETH/BTC.", caplog) + assert isinstance(rate, float) + assert rate == expected + # Use caching + api_mock.fetch_l2_order_book.reset_mock() + api_mock.fetch_ticker.reset_mock() + + rate = exchange.get_rates(pair, refresh=False, is_short=False)[1] + assert rate == expected + assert log_has("Using cached sell rate for ETH/BTC.", caplog) + + assert api_mock.fetch_l2_order_book.call_count == 0 + assert api_mock.fetch_ticker.call_count == 0 + + @pytest.mark.parametrize("exchange_name", EXCHANGES) @pytest.mark.asyncio async def test___async_get_candle_history_sort(default_conf, mocker, exchange_name): diff --git a/tests/optimize/test_backtesting_adjust_position.py b/tests/optimize/test_backtesting_adjust_position.py index fca9c01b2..2bb7de574 100644 --- a/tests/optimize/test_backtesting_adjust_position.py +++ b/tests/optimize/test_backtesting_adjust_position.py @@ -1,8 +1,10 @@ # pragma pylint: disable=missing-docstring, W0212, line-too-long, C0103, unused-argument from copy import deepcopy +from unittest.mock import MagicMock import pandas as pd +import pytest from arrow import Arrow from freqtrade.configuration import TimeRange @@ -87,3 +89,87 @@ def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) -> assert (round(ln.iloc[0]["open"], 6) == round(t["close_rate"], 6) or round(ln.iloc[0]["low"], 6) < round( t["close_rate"], 6) < round(ln.iloc[0]["high"], 6)) + + +def test_backtest_position_adjustment_detailed(default_conf, fee, mocker) -> None: + default_conf['use_exit_signal'] = False + mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) + mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=10) + mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) + patch_exchange(mocker) + default_conf.update({ + "stake_amount": 100.0, + "dry_run_wallet": 1000.0, + "strategy": "StrategyTestV3" + }) + backtesting = Backtesting(default_conf) + backtesting._set_strategy(backtesting.strategylist[0]) + pair = 'XRP/USDT' + row = [ + pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=0), + 2.1, # Open + 2.2, # High + 1.9, # Low + 2.1, # Close + 1, # enter_long + 0, # exit_long + 0, # enter_short + 0, # exit_short + '', # enter_tag + '', # exit_tag + ] + trade = backtesting._enter_trade(pair, row=row, direction='long') + trade.orders[0].close_bt_order(row[0], trade) + assert trade + assert pytest.approx(trade.stake_amount) == 100.0 + assert pytest.approx(trade.amount) == 47.61904762 + assert len(trade.orders) == 1 + backtesting.strategy.adjust_trade_position = MagicMock(return_value=None) + + trade = backtesting._get_adjust_trade_entry_for_candle(trade, row) + assert trade + assert pytest.approx(trade.stake_amount) == 100.0 + assert pytest.approx(trade.amount) == 47.61904762 + assert len(trade.orders) == 1 + # Increase position by 100 + backtesting.strategy.adjust_trade_position = MagicMock(return_value=100) + + trade = backtesting._get_adjust_trade_entry_for_candle(trade, row) + + assert trade + assert pytest.approx(trade.stake_amount) == 200.0 + assert pytest.approx(trade.amount) == 95.23809524 + assert len(trade.orders) == 2 + + # Reduce by more than amount - no change to trade. + backtesting.strategy.adjust_trade_position = MagicMock(return_value=-500) + + trade = backtesting._get_adjust_trade_entry_for_candle(trade, row) + + assert trade + assert pytest.approx(trade.stake_amount) == 200.0 + assert pytest.approx(trade.amount) == 95.23809524 + assert len(trade.orders) == 2 + assert trade.nr_of_successful_entries == 2 + + # Reduce position by 50 + backtesting.strategy.adjust_trade_position = MagicMock(return_value=-100) + trade = backtesting._get_adjust_trade_entry_for_candle(trade, row) + + assert trade + assert pytest.approx(trade.stake_amount) == 100.0 + assert pytest.approx(trade.amount) == 47.61904762 + assert len(trade.orders) == 3 + assert trade.nr_of_successful_entries == 2 + assert trade.nr_of_successful_exits == 1 + + # Adjust below minimum + backtesting.strategy.adjust_trade_position = MagicMock(return_value=-99) + trade = backtesting._get_adjust_trade_entry_for_candle(trade, row) + + assert trade + assert pytest.approx(trade.stake_amount) == 100.0 + assert pytest.approx(trade.amount) == 47.61904762 + assert len(trade.orders) == 3 + assert trade.nr_of_successful_entries == 2 + assert trade.nr_of_successful_exits == 1 diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 6e19fcaf3..02c62e337 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -111,6 +111,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'stoploss_entry_dist': -0.00010475, 'stoploss_entry_dist_ratio': -0.10448878, 'open_order': None, + 'realized_profit': 0.0, 'exchange': 'binance', 'leverage': 1.0, 'interest_rate': 0.0, @@ -196,6 +197,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'stoploss_entry_dist_ratio': -0.10448878, 'open_order': None, 'exchange': 'binance', + 'realized_profit': 0.0, 'leverage': 1.0, 'interest_rate': 0.0, 'liquidation_price': None, @@ -841,7 +843,8 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: 'side': 'sell', 'amount': amount, 'remaining': amount, - 'filled': 0.0 + 'filled': 0.0, + 'id': trade.orders[0].order_id, } ) msg = rpc._rpc_force_exit('3') diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 8d244f3fd..98c06c8e9 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -272,7 +272,7 @@ def test_telegram_status_multi_entry(default_conf, update, mocker, fee) -> None: msg = msg_mock.call_args_list[0][0][0] assert re.search(r'Number of Entries.*2', msg) assert re.search(r'Average Entry Price', msg) - assert re.search(r'Order filled at', msg) + assert re.search(r'Order filled', msg) assert re.search(r'Close Date:', msg) is None assert re.search(r'Close Profit:', msg) is None @@ -959,6 +959,9 @@ def test_telegram_forceexit_handle(default_conf, update, ticker, fee, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, + 'stake_amount': 0.0009999999999054, + 'sub_trade': False, + 'cumulative_profit': 0.0, } == last_msg @@ -1028,6 +1031,9 @@ def test_telegram_force_exit_down_handle(default_conf, update, ticker, fee, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, + 'stake_amount': 0.0009999999999054, + 'sub_trade': False, + 'cumulative_profit': 0.0, } == last_msg @@ -1087,6 +1093,9 @@ def test_forceexit_all_handle(default_conf, update, ticker, fee, mocker) -> None 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, + 'stake_amount': 0.0009999999999054, + 'sub_trade': False, + 'cumulative_profit': 0.0, } == msg @@ -1437,7 +1446,7 @@ def test_whitelist_static(default_conf, update, mocker) -> None: def test_whitelist_dynamic(default_conf, update, mocker) -> None: mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True)) default_conf['pairlists'] = [{'method': 'VolumePairList', - 'number_assets': 4 + 'number_assets': 4 }] telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) @@ -1789,7 +1798,6 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en 'leverage': leverage, 'stake_amount': 0.01465333, 'direction': entered, - # 'stake_amount_fiat': 0.0, 'stake_currency': 'BTC', 'fiat_currency': 'USD', 'open_rate': 1.099e-05, @@ -1806,6 +1814,33 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en '*Total:* `(0.01465333 BTC, 180.895 USD)`' ) + msg_mock.reset_mock() + telegram.send_msg({ + 'type': message_type, + 'trade_id': 1, + 'enter_tag': enter_signal, + 'exchange': 'Binance', + 'pair': 'ETH/BTC', + 'leverage': leverage, + 'stake_amount': 0.01465333, + 'sub_trade': True, + 'direction': entered, + 'stake_currency': 'BTC', + 'fiat_currency': 'USD', + 'open_rate': 1.099e-05, + 'amount': 1333.3333333333335, + 'open_date': arrow.utcnow().shift(hours=-1) + }) + + assert msg_mock.call_args[0][0] == ( + f'\N{CHECK MARK} *Binance (dry):* {entered}ed ETH/BTC (#1)\n' + f'*Enter Tag:* `{enter_signal}`\n' + '*Amount:* `1333.33333333`\n' + f"{leverage_text}" + '*Open Rate:* `0.00001099`\n' + '*Total:* `(0.01465333 BTC, 180.895 USD)`' + ) + def test_send_msg_sell_notification(default_conf, mocker) -> None: @@ -1840,14 +1875,53 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: '*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n' '*Enter Tag:* `buy_signal1`\n' '*Exit Reason:* `stop_loss`\n' - '*Duration:* `1:00:00 (60.0 min)`\n' '*Direction:* `Long`\n' '*Amount:* `1333.33333333`\n' '*Open Rate:* `0.00007500`\n' '*Current Rate:* `0.00003201`\n' - '*Close Rate:* `0.00003201`' + '*Exit Rate:* `0.00003201`\n' + '*Duration:* `1:00:00 (60.0 min)`' ) + msg_mock.reset_mock() + telegram.send_msg({ + 'type': RPCMessageType.EXIT, + 'trade_id': 1, + 'exchange': 'Binance', + 'pair': 'KEY/ETH', + 'direction': 'Long', + 'gain': 'loss', + 'limit': 3.201e-05, + 'amount': 1333.3333333333335, + 'order_type': 'market', + 'open_rate': 7.5e-05, + 'current_rate': 3.201e-05, + 'cumulative_profit': -0.15746268, + 'profit_amount': -0.05746268, + 'profit_ratio': -0.57405275, + 'stake_currency': 'ETH', + 'fiat_currency': 'USD', + 'enter_tag': 'buy_signal1', + 'exit_reason': ExitType.STOP_LOSS.value, + 'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30), + 'close_date': arrow.utcnow(), + 'stake_amount': 0.01, + 'sub_trade': True, + }) + assert msg_mock.call_args[0][0] == ( + '\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n' + '*Unrealized Sub Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n' + '*Cumulative Profit:* (`-0.15746268 ETH / -24.812 USD`)\n' + '*Enter Tag:* `buy_signal1`\n' + '*Exit Reason:* `stop_loss`\n' + '*Direction:* `Long`\n' + '*Amount:* `1333.33333333`\n' + '*Open Rate:* `0.00007500`\n' + '*Current Rate:* `0.00003201`\n' + '*Exit Rate:* `0.00003201`\n' + '*Remaining:* `(0.01 ETH, -24.812 USD)`' + ) + msg_mock.reset_mock() telegram.send_msg({ 'type': RPCMessageType.EXIT, @@ -1871,15 +1945,15 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: }) assert msg_mock.call_args[0][0] == ( '\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n' - '*Unrealized Profit:* `-57.41%`\n' + '*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH)`\n' '*Enter Tag:* `buy_signal1`\n' '*Exit Reason:* `stop_loss`\n' - '*Duration:* `1 day, 2:30:00 (1590.0 min)`\n' '*Direction:* `Long`\n' '*Amount:* `1333.33333333`\n' '*Open Rate:* `0.00007500`\n' '*Current Rate:* `0.00003201`\n' - '*Close Rate:* `0.00003201`' + '*Exit Rate:* `0.00003201`\n' + '*Duration:* `1 day, 2:30:00 (1590.0 min)`' ) # Reset singleton function to avoid random breaks telegram._rpc._fiat_converter.convert_amount = old_convamount @@ -1954,15 +2028,15 @@ def test_send_msg_sell_fill_notification(default_conf, mocker, direction, leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else '' assert msg_mock.call_args[0][0] == ( '\N{WARNING SIGN} *Binance (dry):* Exited KEY/ETH (#1)\n' - '*Profit:* `-57.41%`\n' + '*Profit:* `-57.41% (loss: -0.05746268 ETH)`\n' f'*Enter Tag:* `{enter_signal}`\n' '*Exit Reason:* `stop_loss`\n' - '*Duration:* `1 day, 2:30:00 (1590.0 min)`\n' f"*Direction:* `{direction}`\n" f"{leverage_text}" '*Amount:* `1333.33333333`\n' '*Open Rate:* `0.00007500`\n' - '*Close Rate:* `0.00003201`' + '*Exit Rate:* `0.00003201`\n' + '*Duration:* `1 day, 2:30:00 (1590.0 min)`' ) @@ -2090,16 +2164,16 @@ def test_send_msg_sell_notification_no_fiat( leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else '' assert msg_mock.call_args[0][0] == ( '\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n' - '*Unrealized Profit:* `-57.41%`\n' + '*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH)`\n' f'*Enter Tag:* `{enter_signal}`\n' '*Exit Reason:* `stop_loss`\n' - '*Duration:* `2:35:03 (155.1 min)`\n' f'*Direction:* `{direction}`\n' f'{leverage_text}' '*Amount:* `1333.33333333`\n' '*Open Rate:* `0.00007500`\n' '*Current Rate:* `0.00003201`\n' - '*Close Rate:* `0.00003201`' + '*Exit Rate:* `0.00003201`\n' + '*Duration:* `2:35:03 (155.1 min)`' ) diff --git a/tests/strategy/strats/strategy_test_v3.py b/tests/strategy/strats/strategy_test_v3.py index 2c7ccbdf2..088ab21d4 100644 --- a/tests/strategy/strats/strategy_test_v3.py +++ b/tests/strategy/strats/strategy_test_v3.py @@ -185,9 +185,12 @@ class StrategyTestV3(IStrategy): return 3.0 - def adjust_trade_position(self, trade: Trade, current_time: datetime, current_rate: float, - current_profit: float, - min_stake: Optional[float], max_stake: float, **kwargs): + def adjust_trade_position(self, trade: Trade, current_time: datetime, + current_rate: float, current_profit: float, + min_stake: Optional[float], max_stake: float, + current_entry_rate: float, current_exit_rate: float, + current_entry_profit: float, current_exit_profit: float, + **kwargs) -> Optional[float]: if current_profit < -0.0075: orders = trade.select_filled_orders(trade.entry_side) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 438a2704c..0b073a062 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -843,8 +843,8 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, # In case of closed order order['status'] = 'closed' - order['price'] = 10 - order['cost'] = 100 + order['average'] = 10 + order['cost'] = 300 order['id'] = '444' mocker.patch('freqtrade.exchange.Exchange.create_order', @@ -855,7 +855,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, assert trade assert trade.open_order_id is None assert trade.open_rate == 10 - assert trade.stake_amount == round(order['price'] * order['filled'] / leverage, 8) + assert trade.stake_amount == round(order['average'] * order['filled'] / leverage, 8) assert pytest.approx(trade.liquidation_price) == liq_price # In case of rejected or expired order and partially filled @@ -863,8 +863,8 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, order['amount'] = 30.0 order['filled'] = 20.0 order['remaining'] = 10.00 - order['price'] = 0.5 - order['cost'] = 15.0 + order['average'] = 0.5 + order['cost'] = 10.0 order['id'] = '555' mocker.patch('freqtrade.exchange.Exchange.create_order', MagicMock(return_value=order)) @@ -872,9 +872,9 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, trade = Trade.query.all()[3] trade.is_short = is_short assert trade - assert trade.open_order_id == '555' + assert trade.open_order_id is None assert trade.open_rate == 0.5 - assert trade.stake_amount == round(order['price'] * order['filled'] / leverage, 8) + assert trade.stake_amount == round(order['average'] * order['filled'] / leverage, 8) # Test with custom stake order['status'] = 'open' @@ -901,7 +901,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, order['amount'] = 30.0 * leverage order['filled'] = 0.0 order['remaining'] = 30.0 - order['price'] = 0.5 + order['average'] = 0.5 order['cost'] = 0.0 order['id'] = '66' mocker.patch('freqtrade.exchange.Exchange.create_order', @@ -1083,7 +1083,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_ 'last': 1.9 }), create_order=MagicMock(side_effect=[ - {'id': enter_order['id']}, + enter_order, exit_order, ]), get_fee=fee, @@ -1109,20 +1109,20 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_ # should do nothing and return false trade.is_open = True trade.open_order_id = None - trade.stoploss_order_id = 100 + trade.stoploss_order_id = "100" hanging_stoploss_order = MagicMock(return_value={'status': 'open'}) mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', hanging_stoploss_order) assert freqtrade.handle_stoploss_on_exchange(trade) is False - assert trade.stoploss_order_id == 100 + assert trade.stoploss_order_id == "100" # Third case: when stoploss was set but it was canceled for some reason # should set a stoploss immediately and return False caplog.clear() trade.is_open = True trade.open_order_id = None - trade.stoploss_order_id = 100 + trade.stoploss_order_id = "100" canceled_stoploss_order = MagicMock(return_value={'status': 'canceled'}) mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', canceled_stoploss_order) @@ -2039,6 +2039,7 @@ def test_update_trade_state_exception(mocker, default_conf_usdt, is_short, limit trade = MagicMock() trade.open_order_id = '123' + trade.amount = 123 # Test raise of OperationalException exception mocker.patch( @@ -2352,9 +2353,9 @@ def test_close_trade( trade.is_short = is_short assert trade - oobj = Order.parse_from_ccxt_object(enter_order, enter_order['symbol'], 'buy') + oobj = Order.parse_from_ccxt_object(enter_order, enter_order['symbol'], trade.enter_side) trade.update_trade(oobj) - oobj = Order.parse_from_ccxt_object(exit_order, exit_order['symbol'], 'sell') + oobj = Order.parse_from_ccxt_object(exit_order, exit_order['symbol'], trade.exit_side) trade.update_trade(oobj) assert trade.is_open is False @@ -2397,8 +2398,8 @@ def test_manage_open_orders_entry_usercustom( 'freqtrade.exchange.Exchange', fetch_ticker=ticker_usdt, fetch_order=MagicMock(return_value=old_order), - cancel_order_with_result=cancel_order_wr_mock, cancel_order=cancel_order_mock, + cancel_order_with_result=cancel_order_wr_mock, get_fee=fee ) freqtrade = FreqtradeBot(default_conf_usdt) @@ -2446,7 +2447,9 @@ def test_manage_open_orders_entry( ) -> None: old_order = limit_sell_order_old if is_short else limit_buy_order_old rpc_mock = patch_RPCManager(mocker) - old_order['id'] = open_trade.open_order_id + open_trade.open_order_id = old_order['id'] + order = Order.parse_from_ccxt_object(old_order, 'mocked', 'buy') + open_trade.orders[0] = order limit_buy_cancel = deepcopy(old_order) limit_buy_cancel['status'] = 'canceled' cancel_order_mock = MagicMock(return_value=limit_buy_cancel) @@ -2637,7 +2640,9 @@ def test_manage_open_orders_exit_usercustom( is_short, open_trade_usdt, caplog ) -> None: default_conf_usdt["unfilledtimeout"] = {"entry": 1440, "exit": 1440, "exit_timeout_count": 1} - limit_sell_order_old['id'] = open_trade_usdt.open_order_id + open_trade_usdt.open_order_id = limit_sell_order_old['id'] + order = Order.parse_from_ccxt_object(limit_sell_order_old, 'mocked', 'sell') + open_trade_usdt.orders[0] = order if is_short: limit_sell_order_old['side'] = 'buy' open_trade_usdt.is_short = is_short @@ -3250,6 +3255,9 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_ 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, + 'sub_trade': False, + 'cumulative_profit': 0.0, + 'stake_amount': pytest.approx(60), } == last_msg @@ -3310,6 +3318,9 @@ def test_execute_trade_exit_down(default_conf_usdt, ticker_usdt, fee, ticker_usd 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, + 'sub_trade': False, + 'cumulative_profit': 0.0, + 'stake_amount': pytest.approx(60), } == last_msg @@ -3391,6 +3402,9 @@ def test_execute_trade_exit_custom_exit_price( 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, + 'sub_trade': False, + 'cumulative_profit': 0.0, + 'stake_amount': pytest.approx(60), } == last_msg @@ -3459,6 +3473,9 @@ def test_execute_trade_exit_down_stoploss_on_exchange_dry_run( 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, + 'sub_trade': False, + 'cumulative_profit': 0.0, + 'stake_amount': pytest.approx(60), } == last_msg @@ -3690,7 +3707,7 @@ def test_execute_trade_exit_market_order( ) assert not trade.is_open - assert trade.close_profit == profit_ratio + assert pytest.approx(trade.close_profit) == profit_ratio assert rpc_mock.call_count == 4 last_msg = rpc_mock.call_args_list[-2][0][0] @@ -3718,6 +3735,9 @@ def test_execute_trade_exit_market_order( 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, + 'sub_trade': False, + 'cumulative_profit': 0.0, + 'stake_amount': pytest.approx(60), } == last_msg @@ -3789,7 +3809,7 @@ def test_exit_profit_only( 'last': bid }), create_order=MagicMock(side_effect=[ - limit_order_open[eside], + limit_order[eside], {'id': 1234553382}, ]), get_fee=fee, @@ -4081,7 +4101,7 @@ def test_trailing_stop_loss_positive( 'last': enter_price - (-0.01 if is_short else 0.01), }), create_order=MagicMock(side_effect=[ - limit_order_open[eside], + limit_order[eside], {'id': 1234553382}, ]), get_fee=fee, @@ -4632,7 +4652,7 @@ def test_order_book_entry_pricing1(mocker, default_conf_usdt, order_book_l2, exc with pytest.raises(PricingError): freqtrade.exchange.get_rate('ETH/USDT', side="entry", is_short=False, refresh=True) assert log_has_re( - r'Entry Price at location 1 from orderbook could not be determined.', caplog) + r'ETH/USDT - Entry Price at location 1 from orderbook could not be determined.', caplog) else: assert freqtrade.exchange.get_rate( 'ETH/USDT', side="entry", is_short=False, refresh=True) == 0.043935 @@ -4711,8 +4731,9 @@ def test_order_book_exit_pricing( return_value={'bids': [[]], 'asks': [[]]}) with pytest.raises(PricingError): freqtrade.handle_trade(trade) - assert log_has_re(r'Exit Price at location 1 from orderbook could not be determined\..*', - caplog) + assert log_has_re( + r"ETH/USDT - Exit Price at location 1 from orderbook could not be determined\..*", + caplog) def test_startup_state(default_conf_usdt, mocker): @@ -5385,7 +5406,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None: 'status': None, 'price': 9, 'amount': 12, - 'cost': 100, + 'cost': 108, 'ft_is_open': True, 'id': '651', 'order_id': '651' @@ -5480,7 +5501,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None: assert trade.open_order_id is None assert pytest.approx(trade.open_rate) == 9.90909090909 assert trade.amount == 22 - assert trade.stake_amount == 218 + assert pytest.approx(trade.stake_amount) == 218 orders = Order.query.all() assert orders @@ -5533,6 +5554,329 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None: # Make sure the closed order is found as the second order. order = trade.select_order('buy', False) assert order.order_id == '652' + closed_sell_dca_order_1 = { + 'ft_pair': pair, + 'status': 'closed', + 'ft_order_side': 'sell', + 'side': 'sell', + 'type': 'limit', + 'price': 8, + 'average': 8, + 'amount': 15, + 'filled': 15, + 'cost': 120, + 'ft_is_open': False, + 'id': '653', + 'order_id': '653' + } + mocker.patch('freqtrade.exchange.Exchange.create_order', + MagicMock(return_value=closed_sell_dca_order_1)) + mocker.patch('freqtrade.exchange.Exchange.fetch_order', + MagicMock(return_value=closed_sell_dca_order_1)) + mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', + MagicMock(return_value=closed_sell_dca_order_1)) + assert freqtrade.execute_trade_exit(trade=trade, limit=8, + exit_check=ExitCheckTuple(exit_type=ExitType.PARTIAL_EXIT), + sub_trade_amt=15) + + # Assert trade is as expected (averaged dca) + trade = Trade.query.first() + assert trade + assert trade.open_order_id is None + assert trade.is_open + assert trade.amount == 22 + assert trade.stake_amount == 192.05405405405406 + assert pytest.approx(trade.open_rate) == 8.729729729729 + + orders = Order.query.all() + assert orders + assert len(orders) == 4 + + # Make sure the closed order is found as the second order. + order = trade.select_order('sell', False) + assert order.order_id == '653' + + +def test_position_adjust2(mocker, default_conf_usdt, fee) -> None: + """ + TODO: Should be adjusted to test both long and short + buy 100 @ 11 + sell 50 @ 8 + sell 50 @ 16 + """ + patch_RPCManager(mocker) + patch_exchange(mocker) + patch_wallet(mocker, free=10000) + default_conf_usdt.update({ + "position_adjustment_enable": True, + "dry_run": False, + "stake_amount": 200.0, + "dry_run_wallet": 1000.0, + }) + freqtrade = FreqtradeBot(default_conf_usdt) + freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True) + bid = 11 + amount = 100 + buy_rate_mock = MagicMock(return_value=bid) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + get_rate=buy_rate_mock, + fetch_ticker=MagicMock(return_value={ + 'bid': 10, + 'ask': 12, + 'last': 11 + }), + get_min_pair_stake_amount=MagicMock(return_value=1), + get_fee=fee, + ) + pair = 'ETH/USDT' + # Initial buy + closed_successful_buy_order = { + 'pair': pair, + 'ft_pair': pair, + 'ft_order_side': 'buy', + 'side': 'buy', + 'type': 'limit', + 'status': 'closed', + 'price': bid, + 'average': bid, + 'cost': bid * amount, + 'amount': amount, + 'filled': amount, + 'ft_is_open': False, + 'id': '600', + 'order_id': '600' + } + mocker.patch('freqtrade.exchange.Exchange.create_order', + MagicMock(return_value=closed_successful_buy_order)) + mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', + MagicMock(return_value=closed_successful_buy_order)) + assert freqtrade.execute_entry(pair, amount) + # Should create an closed trade with an no open order id + # Order is filled and trade is open + orders = Order.query.all() + assert orders + assert len(orders) == 1 + trade = Trade.query.first() + assert trade + assert trade.is_open is True + assert trade.open_order_id is None + assert trade.open_rate == bid + assert trade.stake_amount == bid * amount + + # Assume it does nothing since order is closed and trade is open + freqtrade.update_closed_trades_without_assigned_fees() + + trade = Trade.query.first() + assert trade + assert trade.is_open is True + assert trade.open_order_id is None + assert trade.open_rate == bid + assert trade.stake_amount == bid * amount + assert not trade.fee_updated(trade.entry_side) + + freqtrade.manage_open_orders() + + trade = Trade.query.first() + assert trade + assert trade.is_open is True + assert trade.open_order_id is None + assert trade.open_rate == bid + assert trade.stake_amount == bid * amount + assert not trade.fee_updated(trade.entry_side) + + amount = 50 + ask = 8 + closed_sell_dca_order_1 = { + 'ft_pair': pair, + 'status': 'closed', + 'ft_order_side': 'sell', + 'side': 'sell', + 'type': 'limit', + 'price': ask, + 'average': ask, + 'amount': amount, + 'filled': amount, + 'cost': amount * ask, + 'ft_is_open': False, + 'id': '601', + 'order_id': '601' + } + mocker.patch('freqtrade.exchange.Exchange.create_order', + MagicMock(return_value=closed_sell_dca_order_1)) + mocker.patch('freqtrade.exchange.Exchange.fetch_order', + MagicMock(return_value=closed_sell_dca_order_1)) + mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', + MagicMock(return_value=closed_sell_dca_order_1)) + assert freqtrade.execute_trade_exit(trade=trade, limit=ask, + exit_check=ExitCheckTuple(exit_type=ExitType.PARTIAL_EXIT), + sub_trade_amt=amount) + trades: List[Trade] = trade.get_open_trades_without_assigned_fees() + assert len(trades) == 1 + # Assert trade is as expected (averaged dca) + + trade = Trade.query.first() + assert trade + assert trade.open_order_id is None + assert trade.amount == 50 + assert trade.open_rate == 11 + assert trade.stake_amount == 550 + assert pytest.approx(trade.realized_profit) == -152.375 + assert pytest.approx(trade.close_profit_abs) == -152.375 + + orders = Order.query.all() + assert orders + assert len(orders) == 2 + # Make sure the closed order is found as the second order. + order = trade.select_order('sell', False) + assert order.order_id == '601' + + amount = 50 + ask = 16 + closed_sell_dca_order_2 = { + 'ft_pair': pair, + 'status': 'closed', + 'ft_order_side': 'sell', + 'side': 'sell', + 'type': 'limit', + 'price': ask, + 'average': ask, + 'amount': amount, + 'filled': amount, + 'cost': amount * ask, + 'ft_is_open': False, + 'id': '602', + 'order_id': '602' + } + mocker.patch('freqtrade.exchange.Exchange.create_order', + MagicMock(return_value=closed_sell_dca_order_2)) + mocker.patch('freqtrade.exchange.Exchange.fetch_order', + MagicMock(return_value=closed_sell_dca_order_2)) + mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', + MagicMock(return_value=closed_sell_dca_order_2)) + assert freqtrade.execute_trade_exit(trade=trade, limit=ask, + exit_check=ExitCheckTuple(exit_type=ExitType.PARTIAL_EXIT), + sub_trade_amt=amount) + # Assert trade is as expected (averaged dca) + + trade = Trade.query.first() + assert trade + assert trade.open_order_id is None + assert trade.amount == 50 + assert trade.open_rate == 11 + assert trade.stake_amount == 550 + # Trade fully realized + assert pytest.approx(trade.realized_profit) == 94.25 + assert pytest.approx(trade.close_profit_abs) == 94.25 + orders = Order.query.all() + assert orders + assert len(orders) == 3 + + # Make sure the closed order is found as the second order. + order = trade.select_order('sell', False) + assert order.order_id == '602' + assert trade.is_open is False + + +@pytest.mark.parametrize('data', [ + ( + # tuple 1 - side amount, price + # tuple 2 - amount, open_rate, stake_amount, cumulative_profit, realized_profit, rel_profit + (('buy', 100, 10), (100.0, 10.0, 1000.0, 0.0, None, None)), + (('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)), + (('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625, -0.044788)), + (('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875, 0.59201995)), + (('sell', 50, 5), (50.0, 12.5, 625.0, 336.625, 336.625, 0.1343142)), # final profit (sum) + ), + ( + (('buy', 100, 3), (100.0, 3.0, 300.0, 0.0, None, None)), + (('buy', 100, 7), (200.0, 5.0, 1000.0, 0.0, None, None)), + (('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0, 1.189027)), + (('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0, 1.189027)), + (('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5, 0.7186579)), + (('sell', 150, 23), (150.0, 11.0, 1650.0, 3175.75, 3175.75, 0.9747170)), # final profit + ) +]) +def test_position_adjust3(mocker, default_conf_usdt, fee, data) -> None: + default_conf_usdt.update({ + "position_adjustment_enable": True, + "dry_run": False, + "stake_amount": 200.0, + "dry_run_wallet": 1000.0, + }) + patch_RPCManager(mocker) + patch_exchange(mocker) + patch_wallet(mocker, free=10000) + freqtrade = FreqtradeBot(default_conf_usdt) + trade = None + freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True) + for idx, (order, result) in enumerate(data): + amount = order[1] + price = order[2] + price_mock = MagicMock(return_value=price) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + get_rate=price_mock, + fetch_ticker=MagicMock(return_value={ + 'bid': 10, + 'ask': 12, + 'last': 11 + }), + get_min_pair_stake_amount=MagicMock(return_value=1), + get_fee=fee, + ) + pair = 'ETH/USDT' + closed_successful_order = { + 'pair': pair, + 'ft_pair': pair, + 'ft_order_side': order[0], + 'side': order[0], + 'type': 'limit', + 'status': 'closed', + 'price': price, + 'average': price, + 'cost': price * amount, + 'amount': amount, + 'filled': amount, + 'ft_is_open': False, + 'id': f'60{idx}', + 'order_id': f'60{idx}' + } + mocker.patch('freqtrade.exchange.Exchange.create_order', + MagicMock(return_value=closed_successful_order)) + mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', + MagicMock(return_value=closed_successful_order)) + if order[0] == 'buy': + assert freqtrade.execute_entry(pair, amount, trade=trade) + else: + assert freqtrade.execute_trade_exit( + trade=trade, limit=price, + exit_check=ExitCheckTuple(exit_type=ExitType.PARTIAL_EXIT), + sub_trade_amt=amount) + + orders1 = Order.query.all() + assert orders1 + assert len(orders1) == idx + 1 + + trade = Trade.query.first() + assert trade + if idx < len(data) - 1: + assert trade.is_open is True + assert trade.open_order_id is None + assert trade.amount == result[0] + assert trade.open_rate == result[1] + assert trade.stake_amount == result[2] + assert pytest.approx(trade.realized_profit) == result[3] + assert pytest.approx(trade.close_profit_abs) == result[4] + assert pytest.approx(trade.close_profit) == result[5] + + order_obj = trade.select_order(order[0], False) + assert order_obj.order_id == f'60{idx}' + + trade = Trade.query.first() + assert trade + assert trade.open_order_id is None + assert trade.is_open is False def test_process_open_trade_positions_exception(mocker, default_conf_usdt, fee, caplog) -> None: @@ -5556,9 +5900,25 @@ def test_check_and_call_adjust_trade_position(mocker, default_conf_usdt, fee, ca "max_entry_position_adjustment": 0, }) freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) - + buy_rate_mock = MagicMock(return_value=10) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + get_rate=buy_rate_mock, + fetch_ticker=MagicMock(return_value={ + 'bid': 10, + 'ask': 12, + 'last': 11 + }), + get_min_pair_stake_amount=MagicMock(return_value=1), + get_fee=fee, + ) create_mock_trades(fee) caplog.set_level(logging.DEBUG) - + freqtrade.strategy.adjust_trade_position = MagicMock(return_value=10) freqtrade.process_open_trade_positions() assert log_has_re(r"Max adjustment entries for .* has been reached\.", caplog) + + caplog.clear() + freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-10) + freqtrade.process_open_trade_positions() + assert log_has_re(r"LIMIT_SELL has been fulfilled.*", caplog) diff --git a/tests/test_integration.py b/tests/test_integration.py index 83f54becb..40fdb4277 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -6,7 +6,7 @@ from freqtrade.enums import ExitCheckTuple, ExitType from freqtrade.persistence import Trade from freqtrade.persistence.models import Order from freqtrade.rpc.rpc import RPC -from tests.conftest import get_patched_freqtradebot, patch_get_signal +from tests.conftest import get_patched_freqtradebot, log_has_re, patch_get_signal def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, @@ -455,3 +455,60 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, fee, mocker) -> None: # Check the 2 filled orders equal the above amount assert pytest.approx(trade.orders[1].amount) == 30.150753768 assert pytest.approx(trade.orders[-1].amount) == 61.538461232 + + +def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog) -> None: + default_conf_usdt['position_adjustment_enable'] = True + + freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + fetch_ticker=ticker_usdt, + get_fee=fee, + amount_to_precision=lambda s, x, y: y, + price_to_precision=lambda s, x, y: y, + get_min_pair_stake_amount=MagicMock(return_value=10), + ) + + patch_get_signal(freqtrade) + freqtrade.enter_positions() + + assert len(Trade.get_trades().all()) == 1 + trade = Trade.get_trades().first() + assert len(trade.orders) == 1 + assert pytest.approx(trade.stake_amount) == 60 + assert pytest.approx(trade.amount) == 30.0 + assert trade.open_rate == 2.0 + + # Too small size + freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-59) + freqtrade.process() + trade = Trade.get_trades().first() + assert len(trade.orders) == 1 + assert pytest.approx(trade.stake_amount) == 60 + assert pytest.approx(trade.amount) == 30.0 + assert log_has_re("Remaining amount of 1.6.* would be too small.", caplog) + + freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-20) + + freqtrade.process() + trade = Trade.get_trades().first() + assert len(trade.orders) == 2 + assert trade.orders[-1].ft_order_side == 'sell' + assert pytest.approx(trade.stake_amount) == 40.198 + assert pytest.approx(trade.amount) == 20.099 + assert trade.open_rate == 2.0 + assert trade.is_open + caplog.clear() + + # Sell more than what we got (we got ~20 coins left) + # First adjusts the amount to 20 - then rejects. + freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-50) + freqtrade.process() + assert log_has_re("Adjusting amount to trade.amount as it is higher.*", caplog) + assert log_has_re("Remaining amount of 0.0 would be too small.", caplog) + trade = Trade.get_trades().first() + assert len(trade.orders) == 2 + assert trade.orders[-1].ft_order_side == 'sell' + assert pytest.approx(trade.stake_amount) == 40.198 + assert trade.is_open diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 0c1fc01a5..42fcc7413 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -500,7 +500,7 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_ assert trade.close_profit is None assert trade.close_date is None - trade.open_order_id = 'something' + trade.open_order_id = enter_order['id'] oobj = Order.parse_from_ccxt_object(enter_order, 'ADA/USDT', entry_side) trade.orders.append(oobj) trade.update_trade(oobj) @@ -515,7 +515,7 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_ caplog) caplog.clear() - trade.open_order_id = 'something' + trade.open_order_id = enter_order['id'] time_machine.move_to("2022-03-31 21:45:05 +00:00") oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', exit_side) trade.orders.append(oobj) @@ -550,7 +550,7 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee, leverage=1.0, ) - trade.open_order_id = 'something' + trade.open_order_id = 'mocked_market_buy' oobj = Order.parse_from_ccxt_object(market_buy_order_usdt, 'ADA/USDT', 'buy') trade.orders.append(oobj) trade.update_trade(oobj) @@ -565,7 +565,7 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee, caplog.clear() trade.is_open = True - trade.open_order_id = 'something' + trade.open_order_id = 'mocked_market_sell' oobj = Order.parse_from_ccxt_object(market_sell_order_usdt, 'ADA/USDT', 'sell') trade.orders.append(oobj) trade.update_trade(oobj) @@ -630,14 +630,14 @@ def test_calc_open_close_trade_price( trade.open_rate = 2.0 trade.close_rate = 2.2 trade.recalc_open_trade_value() - assert isclose(trade._calc_open_trade_value(), open_value) + assert isclose(trade._calc_open_trade_value(trade.amount, trade.open_rate), open_value) assert isclose(trade.calc_close_trade_value(trade.close_rate), close_value) assert isclose(trade.calc_profit(trade.close_rate), round(profit, 8)) assert pytest.approx(trade.calc_profit_ratio(trade.close_rate)) == profit_ratio @pytest.mark.usefixtures("init_persistence") -def test_trade_close(limit_buy_order_usdt, limit_sell_order_usdt, fee): +def test_trade_close(fee): trade = Trade( pair='ADA/USDT', stake_amount=60.0, @@ -815,7 +815,7 @@ def test_calc_open_trade_value( trade.update_trade(oobj) # Buy @ 2.0 # Get the open rate price with the standard fee rate - assert trade._calc_open_trade_value() == result + assert trade._calc_open_trade_value(trade.amount, trade.open_rate) == result @pytest.mark.parametrize( @@ -905,7 +905,7 @@ def test_calc_close_trade_price( ('binance', False, 1, 1.9, 0.003, -3.3209999, -0.055211970, spot, 0), ('binance', False, 1, 2.2, 0.003, 5.6520000, 0.093965087, spot, 0), - # # FUTURES, funding_fee=1 + # FUTURES, funding_fee=1 ('binance', False, 1, 2.1, 0.0025, 3.6925, 0.06138819, futures, 1), ('binance', False, 3, 2.1, 0.0025, 3.6925, 0.18416458, futures, 1), ('binance', True, 1, 2.1, 0.0025, -2.3074999, -0.03855472, futures, 1), @@ -1191,6 +1191,11 @@ def test_calc_profit( assert pytest.approx(trade.calc_profit(rate=close_rate)) == round(profit, 8) assert pytest.approx(trade.calc_profit_ratio(rate=close_rate)) == round(profit_ratio, 8) + assert pytest.approx(trade.calc_profit(close_rate, trade.amount, + trade.open_rate)) == round(profit, 8) + assert pytest.approx(trade.calc_profit_ratio(close_rate, trade.amount, + trade.open_rate)) == round(profit_ratio, 8) + def test_migrate_new(mocker, default_conf, fee, caplog): """ @@ -1382,7 +1387,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog): assert log_has("trying trades_bak2", caplog) assert log_has("Running database migration for trades - backup: trades_bak2, orders_bak0", caplog) - assert trade.open_trade_value == trade._calc_open_trade_value() + assert trade.open_trade_value == trade._calc_open_trade_value(trade.amount, trade.open_rate) assert trade.close_profit_abs is None orders = trade.orders @@ -1744,6 +1749,7 @@ def test_to_json(fee): 'stake_amount': 0.001, 'trade_duration': None, 'trade_duration_s': None, + 'realized_profit': 0.0, 'close_profit': None, 'close_profit_pct': None, 'close_profit_abs': None, @@ -1820,6 +1826,7 @@ def test_to_json(fee): 'initial_stop_loss_abs': None, 'initial_stop_loss_pct': None, 'initial_stop_loss_ratio': None, + 'realized_profit': 0.0, 'close_profit': None, 'close_profit_pct': None, 'close_profit_abs': None, @@ -2262,7 +2269,7 @@ def test_update_order_from_ccxt(caplog): 'symbol': 'ADA/USDT', 'type': 'limit', 'price': 1234.5, - 'amount': 20.0, + 'amount': 20.0, 'filled': 9, 'remaining': 11, 'status': 'open', @@ -2421,7 +2428,7 @@ def test_recalc_trade_from_orders(fee): ) assert fee.return_value == 0.0025 - assert trade._calc_open_trade_value() == o1_trade_val + assert trade._calc_open_trade_value(trade.amount, trade.open_rate) == o1_trade_val assert trade.amount == o1_amount assert trade.stake_amount == o1_cost assert trade.open_rate == o1_rate @@ -2533,7 +2540,8 @@ def test_recalc_trade_from_orders(fee): assert pytest.approx(trade.fee_open_cost) == o1_fee_cost + o2_fee_cost + o3_fee_cost assert pytest.approx(trade.open_trade_value) == o1_trade_val + o2_trade_val + o3_trade_val - # Just to make sure sell orders are ignored, let's calculate one more time. + # Just to make sure full sell orders are ignored, let's calculate one more time. + sell1 = Order( ft_order_side='sell', ft_pair=trade.pair, @@ -2695,7 +2703,7 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): assert trade.open_trade_value == 2 * o1_trade_val assert trade.nr_of_successful_entries == 2 - # Just to make sure exit orders are ignored, let's calculate one more time. + # Reduce position - this will reduce amount again. sell1 = Order( ft_order_side=exit_side, ft_pair=trade.pair, @@ -2706,7 +2714,7 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): side=exit_side, price=4, average=3, - filled=2, + filled=o1_amount, remaining=1, cost=5, order_date=trade.open_date, @@ -2715,11 +2723,11 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): trade.orders.append(sell1) trade.recalc_trade_from_orders() - assert trade.amount == 2 * o1_amount - assert trade.stake_amount == 2 * o1_amount + assert trade.amount == o1_amount + assert trade.stake_amount == o1_amount assert trade.open_rate == o1_rate - assert trade.fee_open_cost == 2 * o1_fee_cost - assert trade.open_trade_value == 2 * o1_trade_val + assert trade.fee_open_cost == o1_fee_cost + assert trade.open_trade_value == o1_trade_val assert trade.nr_of_successful_entries == 2 # Check with 1 order @@ -2743,11 +2751,11 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): trade.recalc_trade_from_orders() # Calling recalc with single initial order should not change anything - assert trade.amount == 3 * o1_amount - assert trade.stake_amount == 3 * o1_amount + assert trade.amount == 2 * o1_amount + assert trade.stake_amount == 2 * o1_amount assert trade.open_rate == o1_rate - assert trade.fee_open_cost == 3 * o1_fee_cost - assert trade.open_trade_value == 3 * o1_trade_val + assert trade.fee_open_cost == 2 * o1_fee_cost + assert trade.open_trade_value == 2 * o1_trade_val assert trade.nr_of_successful_entries == 3 @@ -2815,3 +2823,144 @@ def test_order_to_ccxt(limit_buy_order_open): del raw_order['stopPrice'] del limit_buy_order_open['datetime'] assert raw_order == limit_buy_order_open + + +@pytest.mark.usefixtures("init_persistence") +@pytest.mark.parametrize('data', [ + { + # tuple 1 - side, amount, price + # tuple 2 - amount, open_rate, stake_amount, cumulative_profit, realized_profit, rel_profit + 'orders': [ + (('buy', 100, 10), (100.0, 10.0, 1000.0, 0.0, None, None)), + (('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)), + (('sell', 50, 12), (150.0, 12.5, 1875.0, -25.0, -25.0, -0.04)), + (('sell', 100, 20), (50.0, 12.5, 625.0, 725.0, 750.0, 0.60)), + (('sell', 50, 5), (50.0, 12.5, 625.0, 350.0, -375.0, -0.60)), + ], + 'end_profit': 350.0, + 'end_profit_ratio': 0.14, + 'fee': 0.0, + }, + { + 'orders': [ + (('buy', 100, 10), (100.0, 10.0, 1000.0, 0.0, None, None)), + (('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)), + (('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625, -0.044788)), + (('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875, 0.59201995)), + (('sell', 50, 5), (50.0, 12.5, 625.0, 336.625, -377.1875, -0.60199501)), + ], + 'end_profit': 336.625, + 'end_profit_ratio': 0.1343142, + 'fee': 0.0025, + }, + { + 'orders': [ + (('buy', 100, 3), (100.0, 3.0, 300.0, 0.0, None, None)), + (('buy', 100, 7), (200.0, 5.0, 1000.0, 0.0, None, None)), + (('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0, 1.189027)), + (('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0, 1.189027)), + (('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5, 0.7186579)), + (('sell', 150, 23), (150.0, 11.0, 1650.0, 3175.75, 1787.25, 1.08048062)), + ], + 'end_profit': 3175.75, + 'end_profit_ratio': 0.9747170, + 'fee': 0.0025, + }, + { + # Test above without fees + 'orders': [ + (('buy', 100, 3), (100.0, 3.0, 300.0, 0.0, None, None)), + (('buy', 100, 7), (200.0, 5.0, 1000.0, 0.0, None, None)), + (('sell', 100, 11), (100.0, 5.0, 500.0, 600.0, 600.0, 1.2)), + (('buy', 150, 15), (250.0, 11.0, 2750.0, 600.0, 600.0, 1.2)), + (('sell', 100, 19), (150.0, 11.0, 1650.0, 1400.0, 800.0, 0.72727273)), + (('sell', 150, 23), (150.0, 11.0, 1650.0, 3200.0, 1800.0, 1.09090909)), + ], + 'end_profit': 3200.0, + 'end_profit_ratio': 0.98461538, + 'fee': 0.0, + }, + { + 'orders': [ + (('buy', 100, 8), (100.0, 8.0, 800.0, 0.0, None, None)), + (('buy', 100, 9), (200.0, 8.5, 1700.0, 0.0, None, None)), + (('sell', 100, 10), (100.0, 8.5, 850.0, 150.0, 150.0, 0.17647059)), + (('buy', 150, 11), (250.0, 10, 2500.0, 150.0, 150.0, 0.17647059)), + (('sell', 100, 12), (150.0, 10.0, 1500.0, 350.0, 350.0, 0.2)), + (('sell', 150, 14), (150.0, 10.0, 1500.0, 950.0, 950.0, 0.40)), + ], + 'end_profit': 950.0, + 'end_profit_ratio': 0.283582, + 'fee': 0.0, + }, +]) +def test_recalc_trade_from_orders_dca(data) -> None: + + pair = 'ETH/USDT' + trade = Trade( + id=2, + pair=pair, + stake_amount=1000, + open_rate=data['orders'][0][0][2], + amount=data['orders'][0][0][1], + is_open=True, + open_date=arrow.utcnow().datetime, + fee_open=data['fee'], + fee_close=data['fee'], + exchange='binance', + is_short=False, + leverage=1.0, + trading_mode=TradingMode.SPOT + ) + Trade.query.session.add(trade) + + for idx, (order, result) in enumerate(data['orders']): + amount = order[1] + price = order[2] + + order_obj = Order( + ft_order_side=order[0], + ft_pair=trade.pair, + order_id=f"order_{order[0]}_{idx}", + ft_is_open=False, + status="closed", + symbol=trade.pair, + order_type="market", + side=order[0], + price=price, + average=price, + filled=amount, + remaining=0, + cost=amount * price, + order_date=arrow.utcnow().shift(hours=-10 + idx).datetime, + order_filled_date=arrow.utcnow().shift(hours=-10 + idx).datetime, + ) + trade.orders.append(order_obj) + trade.recalc_trade_from_orders() + Trade.commit() + + orders1 = Order.query.all() + assert orders1 + assert len(orders1) == idx + 1 + + trade = Trade.query.first() + assert trade + assert len(trade.orders) == idx + 1 + if idx < len(data) - 1: + assert trade.is_open is True + assert trade.open_order_id is None + assert trade.amount == result[0] + assert trade.open_rate == result[1] + assert trade.stake_amount == result[2] + # TODO: enable the below. + assert pytest.approx(trade.realized_profit) == result[3] + # assert pytest.approx(trade.close_profit_abs) == result[4] + assert pytest.approx(trade.close_profit) == result[5] + + trade.close(price) + assert pytest.approx(trade.close_profit_abs) == data['end_profit'] + assert pytest.approx(trade.close_profit) == data['end_profit_ratio'] + assert not trade.is_open + trade = Trade.query.first() + assert trade + assert trade.open_order_id is None From 7a696f58f95839c917d3a95225e86c166fb21afd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 03:01:30 +0000 Subject: [PATCH 171/220] Bump ccxt from 1.91.29 to 1.91.52 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.91.29 to 1.91.52. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.91.29...1.91.52) --- 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 b9e87749d..9aec6af63 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.91.29 +ccxt==1.91.52 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.4 aiohttp==3.8.1 From a75fa26caf915d3235b9e0e7bda794a43441a8b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 03:01:38 +0000 Subject: [PATCH 172/220] Bump scipy from 1.8.1 to 1.9.0 Bumps [scipy](https://github.com/scipy/scipy) from 1.8.1 to 1.9.0. - [Release notes](https://github.com/scipy/scipy/releases) - [Commits](https://github.com/scipy/scipy/compare/v1.8.1...v1.9.0) --- updated-dependencies: - dependency-name: scipy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-hyperopt.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-hyperopt.txt b/requirements-hyperopt.txt index 94e59ec15..cc659fc50 100644 --- a/requirements-hyperopt.txt +++ b/requirements-hyperopt.txt @@ -2,7 +2,7 @@ -r requirements.txt # Required for hyperopt -scipy==1.8.1 +scipy==1.9.0 scikit-learn==1.1.1 scikit-optimize==0.9.0 filelock==3.7.1 From b4ded59c63f6c2fa92e6e1722f0bb6cf758589e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 03:01:43 +0000 Subject: [PATCH 173/220] Bump flake8 from 4.0.1 to 5.0.1 Bumps [flake8](https://github.com/pycqa/flake8) from 4.0.1 to 5.0.1. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/4.0.1...5.0.1) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:development update-type: version-update:semver-major ... 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 3b98e20db..ee7899eeb 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,7 +5,7 @@ -r docs/requirements-docs.txt coveralls==3.3.1 -flake8==4.0.1 +flake8==5.0.1 flake8-tidy-imports==4.8.0 mypy==0.971 pre-commit==2.20.0 From 372be542528457a22ce16f5d408551abe170377e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 03:01:46 +0000 Subject: [PATCH 174/220] Bump types-requests from 2.28.3 to 2.28.6 Bumps [types-requests](https://github.com/python/typeshed) from 2.28.3 to 2.28.6. - [Release notes](https://github.com/python/typeshed/releases) - [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 3b98e20db..d34e551d2 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,6 +24,6 @@ nbconvert==6.5.0 # mypy types types-cachetools==5.2.1 types-filelock==3.2.7 -types-requests==2.28.3 +types-requests==2.28.6 types-tabulate==0.8.11 types-python-dateutil==2.8.19 From ed230dd750e48ecc2148f91ea72bb39cf95dac09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 03:01:52 +0000 Subject: [PATCH 175/220] Bump orjson from 3.7.8 to 3.7.11 Bumps [orjson](https://github.com/ijl/orjson) from 3.7.8 to 3.7.11. - [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.7.8...3.7.11) --- 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 b9e87749d..7aee44d85 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,7 +28,7 @@ py_find_1st==1.1.5 # Load ticker files 30% faster python-rapidjson==1.8 # Properly format api responses -orjson==3.7.8 +orjson==3.7.11 # Notify systemd sdnotify==0.3.2 From 79b650258ee719b5438b37036ef255379aa0fafe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 03:02:02 +0000 Subject: [PATCH 176/220] Bump urllib3 from 1.26.10 to 1.26.11 Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.10 to 1.26.11. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/1.26.11/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.10...1.26.11) --- updated-dependencies: - dependency-name: urllib3 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 b9e87749d..36989119c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ python-telegram-bot==13.13 arrow==1.2.2 cachetools==4.2.2 requests==2.28.1 -urllib3==1.26.10 +urllib3==1.26.11 jsonschema==4.7.2 TA-Lib==0.4.24 technical==1.3.0 From 97064a9ce3bbc25350966a47d1e549f985b076ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 03:13:38 +0000 Subject: [PATCH 177/220] Bump pypa/gh-action-pypi-publish from 1.5.0 to 1.5.1 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.5.0...v1.5.1) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b077be04..bb5bc209e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -351,7 +351,7 @@ jobs: python setup.py sdist bdist_wheel - name: Publish to PyPI (Test) - uses: pypa/gh-action-pypi-publish@v1.5.0 + uses: pypa/gh-action-pypi-publish@v1.5.1 if: (github.event_name == 'release') with: user: __token__ @@ -359,7 +359,7 @@ jobs: repository_url: https://test.pypi.org/legacy/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@v1.5.0 + uses: pypa/gh-action-pypi-publish@v1.5.1 if: (github.event_name == 'release') with: user: __token__ From f3154a4313cb03ea09f3517272b554ccb9b6664a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 04:35:30 +0000 Subject: [PATCH 178/220] Bump jsonschema from 4.7.2 to 4.9.0 Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.7.2 to 4.9.0. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.7.2...v4.9.0) --- updated-dependencies: - dependency-name: jsonschema 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 69f6d1d24..f6ba2a444 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ arrow==1.2.2 cachetools==4.2.2 requests==2.28.1 urllib3==1.26.11 -jsonschema==4.7.2 +jsonschema==4.9.0 TA-Lib==0.4.24 technical==1.3.0 tabulate==0.8.10 From 707a4e7c9eee26ec29749465dda9aa12de69c9bd Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 1 Aug 2022 06:41:08 +0200 Subject: [PATCH 179/220] types-requests bump pre-commit --- .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 759ac0a6a..398d09875 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: additional_dependencies: - types-cachetools==5.2.1 - types-filelock==3.2.7 - - types-requests==2.28.3 + - types-requests==2.28.6 - types-tabulate==0.8.11 - types-python-dateutil==2.8.19 # stages: [push] From d75e0a982091bbe99e5f7795ca83fb56c210617d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 1 Aug 2022 06:43:59 +0200 Subject: [PATCH 180/220] Fix Flake8 errors after flake update --- freqtrade/optimize/backtesting.py | 2 +- freqtrade/optimize/optimize_reports.py | 2 +- freqtrade/persistence/trade_model.py | 8 ++++---- tests/edge/test_edge.py | 2 +- tests/exchange/test_exchange.py | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 46774e8a5..029946cfb 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -595,7 +595,7 @@ class Backtesting: if exit_.exit_type in (ExitType.EXIT_SIGNAL, ExitType.CUSTOM_EXIT): # Checks and adds an exit tag, after checking that the length of the # row has the length for an exit tag column - if( + if ( len(row) > EXIT_TAG_IDX and row[EXIT_TAG_IDX] is not None and len(row[EXIT_TAG_IDX]) > 0 diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 44ac4a5b3..519022db2 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -639,7 +639,7 @@ def text_table_tags(tag_type: str, tag_results: List[Dict[str, Any]], stake_curr :param stake_currency: stake-currency - used to correctly name headers :return: pretty printed table with tabulate as string """ - if(tag_type == "enter_tag"): + if (tag_type == "enter_tag"): headers = _get_line_header("TAG", stake_currency) else: headers = _get_line_header("TAG", stake_currency, 'Sells') diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index fcb84a59a..19d9361b6 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -1300,7 +1300,7 @@ class Trade(_DECL_BASE, LocalTrade): """ filters = [Trade.is_open.is_(False)] - if(pair is not None): + if (pair is not None): filters.append(Trade.pair == pair) enter_tag_perf = Trade.query.with_entities( @@ -1333,7 +1333,7 @@ class Trade(_DECL_BASE, LocalTrade): """ filters = [Trade.is_open.is_(False)] - if(pair is not None): + if (pair is not None): filters.append(Trade.pair == pair) sell_tag_perf = Trade.query.with_entities( @@ -1366,7 +1366,7 @@ class Trade(_DECL_BASE, LocalTrade): """ filters = [Trade.is_open.is_(False)] - if(pair is not None): + if (pair is not None): filters.append(Trade.pair == pair) mix_tag_perf = Trade.query.with_entities( @@ -1386,7 +1386,7 @@ class Trade(_DECL_BASE, LocalTrade): enter_tag = enter_tag if enter_tag is not None else "Other" exit_reason = exit_reason if exit_reason is not None else "Other" - if(exit_reason is not None and enter_tag is not None): + if (exit_reason is not None and enter_tag is not None): mix_tag = enter_tag + " " + exit_reason i = 0 if not any(item["mix_tag"] == mix_tag for item in return_list): diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py index b30d6f998..1b0191fda 100644 --- a/tests/edge/test_edge.py +++ b/tests/edge/test_edge.py @@ -136,7 +136,7 @@ def test_adjust(mocker, edge_conf): )) pairs = ['A/B', 'C/D', 'E/F', 'G/H'] - assert(edge.adjust(pairs) == ['E/F', 'C/D']) + assert (edge.adjust(pairs) == ['E/F', 'C/D']) def test_stoploss(mocker, edge_conf): diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index d73e26683..bbe424430 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3810,8 +3810,8 @@ def test__get_funding_fees_from_exchange(default_conf, mocker, exchange_name): since=unix_time ) - assert(isclose(expected_fees, fees_from_datetime)) - assert(isclose(expected_fees, fees_from_unix_time)) + assert (isclose(expected_fees, fees_from_datetime)) + assert (isclose(expected_fees, fees_from_unix_time)) ccxt_exceptionhandlers( mocker, From ae0d6f63fa458cc2435dcfd8704a2258b7a82358 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 1 Aug 2022 19:43:13 +0200 Subject: [PATCH 181/220] Version bump ccxt to 1.91.55 closes #7151 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f6ba2a444..4cb6519b3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.91.52 +ccxt==1.91.55 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.4 aiohttp==3.8.1 From 95327750dca68592d552e9cbe59347435d2f7fac Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Aug 2022 07:07:54 +0200 Subject: [PATCH 182/220] Final abs. profit should not be doubled in rpc messages --- freqtrade/freqtradebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 757449c8c..657e0bd82 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1566,7 +1566,7 @@ class FreqtradeBot(LoggingMixin): profit_ratio = trade.calc_profit_ratio(profit_rate, amount, trade.open_rate) else: profit_rate = trade.close_rate if trade.close_rate else trade.close_rate_requested - profit = trade.calc_profit(rate=profit_rate) + trade.realized_profit + profit = trade.calc_profit(rate=profit_rate) + (0.0 if fill else trade.realized_profit) profit_ratio = trade.calc_profit_ratio(profit_rate) amount = trade.amount gain = "profit" if profit_ratio > 0 else "loss" From febd809119f1d3cfe30444fbe7978c0ea51e990e Mon Sep 17 00:00:00 2001 From: Stefano Ariestasia Date: Thu, 4 Aug 2022 20:55:52 +0900 Subject: [PATCH 183/220] Fix typo adjust_trade_position should return stake_amount, not amount --- docs/strategy-callbacks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 18de3513b..a9b032818 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -721,7 +721,7 @@ class DigDeeperStrategy(IStrategy): if current_profit > 0.05 and trade.nr_of_successful_exits == 0: # Take half of the profit at +5% - return -(trade.amount / 2) + return -(trade.stake_amount / 2) if current_profit > -0.05: return None From df4a5a75731742dddaa76a76db167f8ccb14eda0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Aug 2022 03:02:12 +0000 Subject: [PATCH 184/220] Bump python from 3.10.5-slim-bullseye to 3.10.6-slim-bullseye Bumps python from 3.10.5-slim-bullseye to 3.10.6-slim-bullseye. --- updated-dependencies: - dependency-name: python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5138ecec9..14a67edc8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10.5-slim-bullseye as base +FROM python:3.10.6-slim-bullseye as base # Setup env ENV LANG C.UTF-8 From debc73b65465a5b9ee9407d854dc30cf9a666fa7 Mon Sep 17 00:00:00 2001 From: OGSK <53548542+Jetsukda@users.noreply.github.com> Date: Fri, 5 Aug 2022 00:28:28 +0700 Subject: [PATCH 185/220] Edit Typo Custom-stake-amount Edit Custom-stake-amount to `custom_stake_amount` --- docs/strategy_migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index 471ffa601..042c2494f 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -192,7 +192,7 @@ class AwesomeStrategy(IStrategy): return False ``` -### Custom-stake-amount +### `custom_stake_amount` New string argument `side` - which can be either `"long"` or `"short"`. From a8541d86fbf0406208e1122f0d346474b6327fb0 Mon Sep 17 00:00:00 2001 From: OGSK <53548542+Jetsukda@users.noreply.github.com> Date: Fri, 5 Aug 2022 09:36:26 +0700 Subject: [PATCH 186/220] Edit index of `custom_stake_amount` --- docs/strategy_migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index 042c2494f..064e7a59d 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -18,7 +18,7 @@ Note : `forcesell`, `forcebuy`, `emergencysell` are changed to `force_exit`, `fo * [`check_buy_timeout()` -> `check_entry_timeout()`](#custom_entry_timeout) * [`check_sell_timeout()` -> `check_exit_timeout()`](#custom_entry_timeout) * New `side` argument to callbacks without trade object - * [`custom_stake_amount`](#custom-stake-amount) + * [`custom_stake_amount`](#custom_stake_amount) * [`confirm_trade_entry`](#confirm_trade_entry) * [`custom_entry_price`](#custom_entry_price) * [Changed argument name in `confirm_trade_exit`](#confirm_trade_exit) From c6e121ffb4cde7fa15326d006fc2d0a062146f4d Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Aug 2022 07:17:58 +0200 Subject: [PATCH 187/220] Update tests with correct usdt mock trades --- tests/conftest_trades_usdt.py | 4 ++-- tests/rpc/test_rpc.py | 32 +++++++++++++------------- tests/rpc/test_rpc_apiserver.py | 32 +++++++++++++------------- tests/rpc/test_rpc_telegram.py | 40 ++++++++++++++++----------------- 4 files changed, 54 insertions(+), 54 deletions(-) diff --git a/tests/conftest_trades_usdt.py b/tests/conftest_trades_usdt.py index 41d705c01..9a89eaca6 100644 --- a/tests/conftest_trades_usdt.py +++ b/tests/conftest_trades_usdt.py @@ -63,7 +63,7 @@ def mock_trade_usdt_1(fee, is_short: bool): open_rate=10.0, close_rate=8.0, close_profit=-0.2, - close_profit_abs=-4.0, + close_profit_abs=-4.09, exchange='binance', strategy='SampleStrategy', open_order_id=f'prod_exit_1_{direc(is_short)}', @@ -183,7 +183,7 @@ def mock_trade_usdt_3(fee, is_short: bool): open_rate=1.0, close_rate=1.1, close_profit=0.1, - close_profit_abs=9.8425, + close_profit_abs=2.8425, exchange='binance', is_open=False, strategy='StrategyTestV2', diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 02c62e337..4c580c3c2 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -314,10 +314,10 @@ def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee, # {'date': datetime.date(2022, 6, 11), 'abs_profit': 13.8299999, # 'starting_balance': 1055.37, 'rel_profit': 0.0131044, # 'fiat_value': 0.0, 'trade_count': 2} - assert day['abs_profit'] in (0.0, pytest.approx(13.8299999), pytest.approx(-4.0)) - assert day['rel_profit'] in (0.0, pytest.approx(0.01310441), pytest.approx(-0.00377583)) + assert day['abs_profit'] in (0.0, pytest.approx(6.83), pytest.approx(-4.09)) + assert day['rel_profit'] in (0.0, pytest.approx(0.00642902), pytest.approx(-0.00383512)) assert day['trade_count'] in (0, 1, 2) - assert day['starting_balance'] in (pytest.approx(1059.37), pytest.approx(1055.37)) + assert day['starting_balance'] in (pytest.approx(1062.37), pytest.approx(1066.46)) assert day['fiat_value'] in (0.0, ) # ensure first day is current date assert str(days['data'][0]['date']) == str(datetime.utcnow().date()) @@ -435,9 +435,9 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None: create_mock_trades_usdt(fee) stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency) - assert pytest.approx(stats['profit_closed_coin']) == 9.83 + assert pytest.approx(stats['profit_closed_coin']) == 2.74 assert pytest.approx(stats['profit_closed_percent_mean']) == -1.67 - assert pytest.approx(stats['profit_closed_fiat']) == 10.813 + assert pytest.approx(stats['profit_closed_fiat']) == 3.014 assert pytest.approx(stats['profit_all_coin']) == -77.45964918 assert pytest.approx(stats['profit_all_percent_mean']) == -57.86 assert pytest.approx(stats['profit_all_fiat']) == -85.205614098 @@ -870,9 +870,9 @@ def test_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None: res = rpc._rpc_performance() assert len(res) == 3 - assert res[0]['pair'] == 'XRP/USDT' + assert res[0]['pair'] == 'ETC/USDT' assert res[0]['count'] == 1 - assert res[0]['profit_pct'] == 10.0 + assert res[0]['profit_pct'] == 5.0 def test_enter_tag_performance_handle(default_conf, ticker, fee, mocker) -> None: @@ -896,16 +896,16 @@ def test_enter_tag_performance_handle(default_conf, ticker, fee, mocker) -> None res = rpc._rpc_enter_tag_performance(None) assert len(res) == 3 - assert res[0]['enter_tag'] == 'TEST3' + assert res[0]['enter_tag'] == 'TEST1' assert res[0]['count'] == 1 - assert res[0]['profit_pct'] == 10.0 + assert res[0]['profit_pct'] == 5.0 res = rpc._rpc_enter_tag_performance(None) assert len(res) == 3 - assert res[0]['enter_tag'] == 'TEST3' + assert res[0]['enter_tag'] == 'TEST1' assert res[0]['count'] == 1 - assert res[0]['profit_pct'] == 10.0 + assert res[0]['profit_pct'] == 5.0 def test_enter_tag_performance_handle_2(mocker, default_conf, markets, fee): @@ -956,11 +956,11 @@ def test_exit_reason_performance_handle(default_conf_usdt, ticker, fee, mocker) res = rpc._rpc_exit_reason_performance(None) assert len(res) == 3 - assert res[0]['exit_reason'] == 'roi' + assert res[0]['exit_reason'] == 'exit_signal' assert res[0]['count'] == 1 - assert res[0]['profit_pct'] == 10.0 + assert res[0]['profit_pct'] == 5.0 - assert res[1]['exit_reason'] == 'exit_signal' + assert res[1]['exit_reason'] == 'roi' assert res[2]['exit_reason'] == 'Other' @@ -1012,9 +1012,9 @@ def test_mix_tag_performance_handle(default_conf, ticker, fee, mocker) -> None: res = rpc._rpc_mix_tag_performance(None) assert len(res) == 3 - assert res[0]['mix_tag'] == 'TEST3 roi' + assert res[0]['mix_tag'] == 'TEST1 exit_signal' assert res[0]['count'] == 1 - assert res[0]['profit_pct'] == 10.0 + assert res[0]['profit_pct'] == 5.0 def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee): diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 57ba8e9f1..c6507d0ae 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -790,22 +790,22 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short, expected) 'first_trade_timestamp': ANY, 'latest_trade_date': '5 minutes ago', 'latest_trade_timestamp': ANY, - 'profit_all_coin': expected['profit_all_coin'], - 'profit_all_fiat': expected['profit_all_fiat'], - 'profit_all_percent_mean': expected['profit_all_percent_mean'], - 'profit_all_ratio_mean': expected['profit_all_ratio_mean'], - 'profit_all_percent_sum': expected['profit_all_percent_sum'], - 'profit_all_ratio_sum': expected['profit_all_ratio_sum'], - 'profit_all_percent': expected['profit_all_percent'], - 'profit_all_ratio': expected['profit_all_ratio'], - 'profit_closed_coin': expected['profit_closed_coin'], - 'profit_closed_fiat': expected['profit_closed_fiat'], - 'profit_closed_ratio_mean': expected['profit_closed_ratio_mean'], - 'profit_closed_percent_mean': expected['profit_closed_percent_mean'], - 'profit_closed_ratio_sum': expected['profit_closed_ratio_sum'], - 'profit_closed_percent_sum': expected['profit_closed_percent_sum'], - 'profit_closed_ratio': expected['profit_closed_ratio'], - 'profit_closed_percent': expected['profit_closed_percent'], + 'profit_all_coin': pytest.approx(expected['profit_all_coin']), + 'profit_all_fiat': pytest.approx(expected['profit_all_fiat']), + 'profit_all_percent_mean': pytest.approx(expected['profit_all_percent_mean']), + 'profit_all_ratio_mean': pytest.approx(expected['profit_all_ratio_mean']), + 'profit_all_percent_sum': pytest.approx(expected['profit_all_percent_sum']), + 'profit_all_ratio_sum': pytest.approx(expected['profit_all_ratio_sum']), + 'profit_all_percent': pytest.approx(expected['profit_all_percent']), + 'profit_all_ratio': pytest.approx(expected['profit_all_ratio']), + 'profit_closed_coin': pytest.approx(expected['profit_closed_coin']), + 'profit_closed_fiat': pytest.approx(expected['profit_closed_fiat']), + 'profit_closed_ratio_mean': pytest.approx(expected['profit_closed_ratio_mean']), + 'profit_closed_percent_mean': pytest.approx(expected['profit_closed_percent_mean']), + 'profit_closed_ratio_sum': pytest.approx(expected['profit_closed_ratio_sum']), + 'profit_closed_percent_sum': pytest.approx(expected['profit_closed_percent_sum']), + 'profit_closed_ratio': pytest.approx(expected['profit_closed_ratio']), + 'profit_closed_percent': pytest.approx(expected['profit_closed_percent']), 'trade_count': 6, 'closed_trade_count': 2, 'winning_trades': expected['winning_trades'], diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 98c06c8e9..9508a6b42 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -433,10 +433,10 @@ def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker, time_machi assert "Daily Profit over the last 2 days:" in msg_mock.call_args_list[0][0][0] assert 'Day ' in msg_mock.call_args_list[0][0][0] assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0] - assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0] - assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0] + assert ' 6.83 USDT' in msg_mock.call_args_list[0][0][0] + assert ' 7.51 USD' in msg_mock.call_args_list[0][0][0] assert '(2)' in msg_mock.call_args_list[0][0][0] - assert '(2) 13.83 USDT 15.21 USD 1.31%' in msg_mock.call_args_list[0][0][0] + assert '(2) 6.83 USDT 7.51 USD 0.64%' in msg_mock.call_args_list[0][0][0] assert '(0)' in msg_mock.call_args_list[0][0][0] # Reset msg_mock @@ -447,8 +447,8 @@ def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker, time_machi assert "Daily Profit over the last 7 days:" in msg_mock.call_args_list[0][0][0] assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0] assert str((datetime.utcnow() - timedelta(days=5)).date()) in msg_mock.call_args_list[0][0][0] - assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0] - assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0] + assert ' 6.83 USDT' in msg_mock.call_args_list[0][0][0] + assert ' 7.51 USD' in msg_mock.call_args_list[0][0][0] assert '(2)' in msg_mock.call_args_list[0][0][0] assert '(1)' in msg_mock.call_args_list[0][0][0] assert '(0)' in msg_mock.call_args_list[0][0][0] @@ -460,8 +460,8 @@ def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker, time_machi context = MagicMock() context.args = ["1"] telegram._daily(update=update, context=context) - assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0] - assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0] + assert ' 6.83 USDT' in msg_mock.call_args_list[0][0][0] + assert ' 7.51 USD' in msg_mock.call_args_list[0][0][0] assert '(2)' in msg_mock.call_args_list[0][0][0] @@ -523,8 +523,8 @@ def test_weekly_handle(default_conf_usdt, update, ticker, fee, mocker, time_mach today = datetime.utcnow().date() first_iso_day_of_current_week = today - timedelta(days=today.weekday()) assert str(first_iso_day_of_current_week) in msg_mock.call_args_list[0][0][0] - assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0] - assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0] + assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0] + assert ' 3.01 USD' in msg_mock.call_args_list[0][0][0] assert '(3)' in msg_mock.call_args_list[0][0][0] assert '(0)' in msg_mock.call_args_list[0][0][0] @@ -536,8 +536,8 @@ def test_weekly_handle(default_conf_usdt, update, ticker, fee, mocker, time_mach assert "Weekly Profit over the last 8 weeks (starting from Monday):" \ in msg_mock.call_args_list[0][0][0] assert 'Weekly' in msg_mock.call_args_list[0][0][0] - assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0] - assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0] + assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0] + assert ' 3.01 USD' in msg_mock.call_args_list[0][0][0] assert '(3)' in msg_mock.call_args_list[0][0][0] assert '(0)' in msg_mock.call_args_list[0][0][0] @@ -592,8 +592,8 @@ def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker, time_mac today = datetime.utcnow().date() current_month = f"{today.year}-{today.month:02} " assert current_month in msg_mock.call_args_list[0][0][0] - assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0] - assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0] + assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0] + assert ' 3.01 USD' in msg_mock.call_args_list[0][0][0] assert '(3)' in msg_mock.call_args_list[0][0][0] assert '(0)' in msg_mock.call_args_list[0][0][0] @@ -606,8 +606,8 @@ def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker, time_mac assert 'Monthly Profit over the last 6 months:' in msg_mock.call_args_list[0][0][0] assert 'Month ' in msg_mock.call_args_list[0][0][0] assert current_month in msg_mock.call_args_list[0][0][0] - assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0] - assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0] + assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0] + assert ' 3.01 USD' in msg_mock.call_args_list[0][0][0] assert '(3)' in msg_mock.call_args_list[0][0][0] assert '(0)' in msg_mock.call_args_list[0][0][0] @@ -620,8 +620,8 @@ def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker, time_mac telegram._monthly(update=update, context=context) assert msg_mock.call_count == 1 assert 'Monthly Profit over the last 12 months:' in msg_mock.call_args_list[0][0][0] - assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0] - assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0] + assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0] + assert ' 3.01 USD' in msg_mock.call_args_list[0][0][0] assert '(3)' in msg_mock.call_args_list[0][0][0] # The one-digit months should contain a zero, Eg: September 2021 = "2021-09" @@ -1268,7 +1268,7 @@ def test_telegram_performance_handle(default_conf_usdt, update, ticker, fee, moc telegram._performance(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert 'Performance' in msg_mock.call_args_list[0][0][0] - assert 'XRP/USDT\t9.842 USDT (10.00%) (1)' in msg_mock.call_args_list[0][0][0] + assert 'XRP/USDT\t2.842 USDT (10.00%) (1)' in msg_mock.call_args_list[0][0][0] def test_telegram_entry_tag_performance_handle( @@ -1318,7 +1318,7 @@ def test_telegram_exit_reason_performance_handle(default_conf_usdt, update, tick telegram._exit_reason_performance(update=update, context=context) assert msg_mock.call_count == 1 assert 'Exit Reason Performance' in msg_mock.call_args_list[0][0][0] - assert 'roi\t9.842 USDT (10.00%) (1)' in msg_mock.call_args_list[0][0][0] + assert 'roi\t2.842 USDT (10.00%) (1)' in msg_mock.call_args_list[0][0][0] context.args = ['XRP/USDT'] telegram._exit_reason_performance(update=update, context=context) @@ -1350,7 +1350,7 @@ def test_telegram_mix_tag_performance_handle(default_conf_usdt, update, ticker, telegram._mix_tag_performance(update=update, context=context) assert msg_mock.call_count == 1 assert 'Mix Tag Performance' in msg_mock.call_args_list[0][0][0] - assert ('TEST3 roi\t9.842 USDT (10.00%) (1)' + assert ('TEST3 roi\t2.842 USDT (10.00%) (1)' in msg_mock.call_args_list[0][0][0]) context.args = ['XRP/USDT'] From cffc7695491d39e653b229d7a1ec75f2cb0ca48b Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Aug 2022 07:26:41 +0200 Subject: [PATCH 188/220] Fix /profit endpoint calculations for partial sells * don't recalculate for closed trades * include realized_profit in the calculation part of #7178 --- freqtrade/rpc/rpc.py | 13 +++++++------ tests/rpc/test_rpc_apiserver.py | 24 ++++++++++++------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 9d6696803..7e431ece9 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -431,14 +431,15 @@ class RPC: if not trade.is_open: profit_ratio = trade.close_profit - profit_closed_coin.append(trade.close_profit_abs) + profit_abs = trade.close_profit_abs + profit_closed_coin.append(profit_abs) profit_closed_ratio.append(profit_ratio) if trade.close_profit >= 0: winning_trades += 1 - winning_profit += trade.close_profit_abs + winning_profit += profit_abs else: losing_trades += 1 - losing_profit += trade.close_profit_abs + losing_profit += profit_abs else: # Get current rate try: @@ -447,10 +448,10 @@ class RPC: except (PricingError, ExchangeError): current_rate = NAN profit_ratio = trade.calc_profit_ratio(rate=current_rate) + profit_abs = trade.calc_profit( + rate=trade.close_rate or current_rate) + trade.realized_profit - profit_all_coin.append( - trade.calc_profit(rate=trade.close_rate or current_rate) - ) + profit_all_coin.append(profit_abs) profit_all_ratio.append(profit_ratio) best_pair = Trade.get_best_pair(start_date) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index c6507d0ae..b7161e680 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -717,11 +717,11 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets): ( True, {'best_pair': 'ETC/BTC', 'best_rate': -0.5, 'best_pair_profit_ratio': -0.005, - 'profit_all_coin': 43.61269123, - 'profit_all_fiat': 538398.67323435, 'profit_all_percent_mean': 66.41, + 'profit_all_coin': 45.561959, + 'profit_all_fiat': 562462.39126200, 'profit_all_percent_mean': 66.41, 'profit_all_ratio_mean': 0.664109545, 'profit_all_percent_sum': 398.47, - 'profit_all_ratio_sum': 3.98465727, 'profit_all_percent': 4.36, - 'profit_all_ratio': 0.043612222872799825, 'profit_closed_coin': -0.00673913, + 'profit_all_ratio_sum': 3.98465727, 'profit_all_percent': 4.56, + 'profit_all_ratio': 0.04556147, 'profit_closed_coin': -0.00673913, 'profit_closed_fiat': -83.19455985, 'profit_closed_ratio_mean': -0.0075, 'profit_closed_percent_mean': -0.75, 'profit_closed_ratio_sum': -0.015, 'profit_closed_percent_sum': -1.5, 'profit_closed_ratio': -6.739057628404269e-06, @@ -732,11 +732,11 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets): ( False, {'best_pair': 'XRP/BTC', 'best_rate': 1.0, 'best_pair_profit_ratio': 0.01, - 'profit_all_coin': -44.0631579, - 'profit_all_fiat': -543959.6842755, 'profit_all_percent_mean': -66.41, + 'profit_all_coin': -45.79641127, + 'profit_all_fiat': -565356.69712815, 'profit_all_percent_mean': -66.41, 'profit_all_ratio_mean': -0.6641100666666667, 'profit_all_percent_sum': -398.47, - 'profit_all_ratio_sum': -3.9846604, 'profit_all_percent': -4.41, - 'profit_all_ratio': -0.044063014216106644, 'profit_closed_coin': 0.00073913, + 'profit_all_ratio_sum': -3.9846604, 'profit_all_percent': -4.58, + 'profit_all_ratio': -0.045796261934205953, 'profit_closed_coin': 0.00073913, 'profit_closed_fiat': 9.124559849999999, 'profit_closed_ratio_mean': 0.0075, 'profit_closed_percent_mean': 0.75, 'profit_closed_ratio_sum': 0.015, 'profit_closed_percent_sum': 1.5, 'profit_closed_ratio': 7.391275897987988e-07, @@ -747,11 +747,11 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets): ( None, {'best_pair': 'XRP/BTC', 'best_rate': 1.0, 'best_pair_profit_ratio': 0.01, - 'profit_all_coin': -14.43790415, - 'profit_all_fiat': -178235.92673175, 'profit_all_percent_mean': 0.08, + 'profit_all_coin': -14.94732578, + 'profit_all_fiat': -184524.7367541, 'profit_all_percent_mean': 0.08, 'profit_all_ratio_mean': 0.000835751666666662, 'profit_all_percent_sum': 0.5, - 'profit_all_ratio_sum': 0.005014509999999972, 'profit_all_percent': -1.44, - 'profit_all_ratio': -0.014437768014451796, 'profit_closed_coin': -0.00542913, + 'profit_all_ratio_sum': 0.005014509999999972, 'profit_all_percent': -1.49, + 'profit_all_ratio': -0.014947184841095841, 'profit_closed_coin': -0.00542913, 'profit_closed_fiat': -67.02260985, 'profit_closed_ratio_mean': 0.0025, 'profit_closed_percent_mean': 0.25, 'profit_closed_ratio_sum': 0.005, 'profit_closed_percent_sum': 0.5, 'profit_closed_ratio': -5.429078808526421e-06, From 7675187c377865abe6d4fc3f58543e294ae7cb53 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Aug 2022 07:29:49 +0200 Subject: [PATCH 189/220] Use telegram message length to avoid constants --- freqtrade/rpc/telegram.py | 18 ++++++++---------- tests/rpc/test_rpc_telegram.py | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 66192fb16..84b051255 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -16,8 +16,8 @@ from typing import Any, Callable, Dict, List, Optional, Union import arrow from tabulate import tabulate -from telegram import (CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, - ParseMode, ReplyKeyboardMarkup, Update) +from telegram import (MAX_MESSAGE_LENGTH, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, + KeyboardButton, ParseMode, ReplyKeyboardMarkup, Update) from telegram.error import BadRequest, NetworkError, TelegramError from telegram.ext import CallbackContext, CallbackQueryHandler, CommandHandler, Updater from telegram.utils.helpers import escape_markdown @@ -35,8 +35,6 @@ logger = logging.getLogger(__name__) logger.debug('Included module rpc.telegram ...') -MAX_TELEGRAM_MESSAGE_LENGTH = 4096 - @dataclass class TimeunitMappings: @@ -908,7 +906,7 @@ class Telegram(RPCHandler): total_dust_currencies += 1 # Handle overflowing message length - if len(output + curr_output) >= MAX_TELEGRAM_MESSAGE_LENGTH: + if len(output + curr_output) >= MAX_MESSAGE_LENGTH: self._send_msg(output) output = curr_output else: @@ -1171,7 +1169,7 @@ class Telegram(RPCHandler): f"({trade['profit_ratio']:.2%}) " f"({trade['count']})\n") - if len(output + stat_line) >= MAX_TELEGRAM_MESSAGE_LENGTH: + if len(output + stat_line) >= MAX_MESSAGE_LENGTH: self._send_msg(output, parse_mode=ParseMode.HTML) output = stat_line else: @@ -1206,7 +1204,7 @@ class Telegram(RPCHandler): f"({trade['profit_ratio']:.2%}) " f"({trade['count']})\n") - if len(output + stat_line) >= MAX_TELEGRAM_MESSAGE_LENGTH: + if len(output + stat_line) >= MAX_MESSAGE_LENGTH: self._send_msg(output, parse_mode=ParseMode.HTML) output = stat_line else: @@ -1241,7 +1239,7 @@ class Telegram(RPCHandler): f"({trade['profit_ratio']:.2%}) " f"({trade['count']})\n") - if len(output + stat_line) >= MAX_TELEGRAM_MESSAGE_LENGTH: + if len(output + stat_line) >= MAX_MESSAGE_LENGTH: self._send_msg(output, parse_mode=ParseMode.HTML) output = stat_line else: @@ -1276,7 +1274,7 @@ class Telegram(RPCHandler): f"({trade['profit']:.2%}) " f"({trade['count']})\n") - if len(output + stat_line) >= MAX_TELEGRAM_MESSAGE_LENGTH: + if len(output + stat_line) >= MAX_MESSAGE_LENGTH: self._send_msg(output, parse_mode=ParseMode.HTML) output = stat_line else: @@ -1415,7 +1413,7 @@ class Telegram(RPCHandler): escape_markdown(logrec[2], version=2), escape_markdown(logrec[3], version=2), escape_markdown(logrec[4], version=2)) - if len(msgs + msg) + 10 >= MAX_TELEGRAM_MESSAGE_LENGTH: + if len(msgs + msg) + 10 >= MAX_MESSAGE_LENGTH: # Send message immediately if it would become too long self._send_msg(msgs, parse_mode=ParseMode.MARKDOWN_V2) msgs = msg + '\n' diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 9508a6b42..164ed0bc6 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1516,7 +1516,7 @@ def test_telegram_logs(default_conf, update, mocker) -> None: msg_mock.reset_mock() # Test with changed MaxMessageLength - mocker.patch('freqtrade.rpc.telegram.MAX_TELEGRAM_MESSAGE_LENGTH', 200) + mocker.patch('freqtrade.rpc.telegram.MAX_MESSAGE_LENGTH', 200) context = MagicMock() context.args = [] telegram._logs(update=update, context=context) From 29e41cc8179f3c8514452e583c5037245131290b Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Aug 2022 11:15:44 +0200 Subject: [PATCH 190/220] Update docs to reflect correct result closes #7181 --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index 412571674..d5c0b3d8b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -105,7 +105,7 @@ This is similar to using multiple `--config` parameters, but simpler in usage as ``` json title="Result" { - "max_open_trades": 10, + "max_open_trades": 3, "stake_currency": "USDT", "stake_amount": "unlimited" } From 954540245209b1a79f707ba51e9e1b7c0f65c18e Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Aug 2022 11:49:51 +0200 Subject: [PATCH 191/220] Improve defaults for config builder --- freqtrade/commands/build_config_commands.py | 6 +++--- freqtrade/templates/base_config.json.j2 | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/freqtrade/commands/build_config_commands.py b/freqtrade/commands/build_config_commands.py index be881c8ed..01cfa800a 100644 --- a/freqtrade/commands/build_config_commands.py +++ b/freqtrade/commands/build_config_commands.py @@ -67,7 +67,7 @@ def ask_user_config() -> Dict[str, Any]: "type": "text", "name": "stake_amount", "message": f"Please insert your stake amount (Number or '{UNLIMITED_STAKE_AMOUNT}'):", - "default": "100", + "default": "unlimited", "validate": lambda val: val == UNLIMITED_STAKE_AMOUNT or validate_is_float(val), "filter": lambda val: '"' + UNLIMITED_STAKE_AMOUNT + '"' if val == UNLIMITED_STAKE_AMOUNT @@ -164,7 +164,7 @@ def ask_user_config() -> Dict[str, Any]: "when": lambda x: x['telegram'] }, { - "type": "text", + "type": "password", "name": "telegram_chat_id", "message": "Insert Telegram chat id", "when": lambda x: x['telegram'] @@ -191,7 +191,7 @@ def ask_user_config() -> Dict[str, Any]: "when": lambda x: x['api_server'] }, { - "type": "text", + "type": "password", "name": "api_server_password", "message": "Insert api-server password", "when": lambda x: x['api_server'] diff --git a/freqtrade/templates/base_config.json.j2 b/freqtrade/templates/base_config.json.j2 index 914aa964b..681af84c6 100644 --- a/freqtrade/templates/base_config.json.j2 +++ b/freqtrade/templates/base_config.json.j2 @@ -12,6 +12,7 @@ "tradable_balance_ratio": 0.99, "fiat_display_currency": "{{ fiat_display_currency }}",{{ ('\n "timeframe": "' + timeframe + '",') if timeframe else '' }} "dry_run": {{ dry_run | lower }}, + "dry_run_wallet": 1000, "cancel_open_orders_on_exit": false, "trading_mode": "{{ trading_mode }}", "margin_mode": "{{ margin_mode }}", From b12dd15f4fcf41f912d0448a56725ab32b6fe98e Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Aug 2022 09:10:12 +0200 Subject: [PATCH 192/220] Send multiple messages in /status if required --- freqtrade/rpc/telegram.py | 21 +++++++++++++-------- tests/rpc/test_rpc_telegram.py | 4 ++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 84b051255..c879676dc 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -457,11 +457,12 @@ class Telegram(RPCHandler): """ Prepare details of trade with entry adjustment enabled """ - lines: List[str] = [] + lines_detail: List[str] = [] if len(filled_orders) > 0: first_avg = filled_orders[0]["safe_price"] for x, order in enumerate(filled_orders): + lines: List[str] = [] if order['is_open'] is True: continue wording = 'Entry' if order['ft_is_entry'] else 'Exit' @@ -507,7 +508,8 @@ class Telegram(RPCHandler): # minutes, seconds = divmod(remainder, 60) # lines.append( # f"({days}d {hours}h {minutes}m {seconds}s from previous {wording.lower()})") - return lines + lines_detail.append("\n".join(lines)) + return lines_detail @authorized_only def _status(self, update: Update, context: CallbackContext) -> None: @@ -541,7 +543,6 @@ class Telegram(RPCHandler): results = self._rpc._rpc_trade_status(trade_ids=trade_ids) position_adjust = self._config.get('position_adjustment_enable', False) max_entries = self._config.get('max_entry_position_adjustment', -1) - messages = [] for r in results: r['open_date_hum'] = arrow.get(r['open_date']).humanize() r['num_entries'] = len([o for o in r['orders'] if o['ft_is_entry']]) @@ -594,12 +595,16 @@ class Telegram(RPCHandler): lines_detail = self._prepare_order_details( r['orders'], r['quote_currency'], r['is_open']) lines.extend(lines_detail if lines_detail else "") + msg = '' + for line in lines: + if line: + if (len(msg) + len(line) + 1) < MAX_MESSAGE_LENGTH: + msg += line + '\n' + else: + self._send_msg(msg.format(**r)) + msg = "*Trade ID:* `{trade_id}` - continued\n" + line + '\n' - # Filter empty lines using list-comprehension - messages.append("\n".join([line for line in lines if line]).format(**r)) - - for msg in messages: - self._send_msg(msg) + self._send_msg(msg.format(**r)) except RPCException as e: self._send_msg(str(e)) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 164ed0bc6..5b96a8068 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -342,7 +342,7 @@ def test_status_handle(default_conf, update, ticker, fee, mocker) -> None: # close_rate should not be included in the message as the trade is not closed # and no line should be empty lines = msg_mock.call_args_list[0][0][0].split('\n') - assert '' not in lines + assert '' not in lines[:-1] assert 'Close Rate' not in ''.join(lines) assert 'Close Profit' not in ''.join(lines) @@ -357,7 +357,7 @@ def test_status_handle(default_conf, update, ticker, fee, mocker) -> None: telegram._status(update=update, context=context) lines = msg_mock.call_args_list[0][0][0].split('\n') - assert '' not in lines + assert '' not in lines[:-1] assert 'Close Rate' not in ''.join(lines) assert 'Close Profit' not in ''.join(lines) From 2687633941eb1c5cee8c0e2ea2a20da86bc20c84 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Aug 2022 09:15:25 +0200 Subject: [PATCH 193/220] Test iterative sending of /status --- freqtrade/rpc/telegram.py | 2 +- tests/rpc/test_rpc_telegram.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index c879676dc..65e16cd35 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -549,7 +549,7 @@ class Telegram(RPCHandler): r['exit_reason'] = r.get('exit_reason', "") lines = [ "*Trade ID:* `{trade_id}`" + - ("` (since {open_date_hum})`" if r['is_open'] else ""), + (" `(since {open_date_hum})`" if r['is_open'] else ""), "*Current Pair:* {pair}", "*Direction:* " + ("`Short`" if r.get('is_short') else "`Long`"), "*Leverage:* `{leverage}`" if r.get('leverage') else "", diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 5b96a8068..2c9528b5e 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -364,6 +364,22 @@ def test_status_handle(default_conf, update, ticker, fee, mocker) -> None: assert msg_mock.call_count == 2 assert 'LTC/BTC' in msg_mock.call_args_list[0][0][0] + mocker.patch('freqtrade.rpc.telegram.MAX_MESSAGE_LENGTH', 500) + + msg_mock.reset_mock() + context = MagicMock() + context.args = ["2"] + telegram._status(update=update, context=context) + + assert msg_mock.call_count == 2 + + msg1 = msg_mock.call_args_list[0][0][0] + msg2 = msg_mock.call_args_list[1][0][0] + + assert 'Close Rate' not in msg1 + assert 'Trade ID:* `2`' in msg1 + assert 'Trade ID:* `2` - continued' in msg2 + def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None: mocker.patch.multiple( From f8f1ade16387b327a7cfa6db33b3dec71557f558 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Aug 2022 09:21:11 +0200 Subject: [PATCH 194/220] Reduce function complexity by extracting message sending --- freqtrade/rpc/telegram.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 65e16cd35..02fb5b4ee 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -587,28 +587,34 @@ class Telegram(RPCHandler): lines.append("*Stoploss distance:* `{stoploss_current_dist:.8f}` " "`({stoploss_current_dist_ratio:.2%})`") if r['open_order']: - if r['exit_order_status']: - lines.append("*Open Order:* `{open_order}` - `{exit_order_status}`") - else: - lines.append("*Open Order:* `{open_order}`") + lines.append( + "*Open Order:* `{open_order}`" + + "- `{exit_order_status}`" if r['exit_order_status'] else "") lines_detail = self._prepare_order_details( r['orders'], r['quote_currency'], r['is_open']) lines.extend(lines_detail if lines_detail else "") - msg = '' - for line in lines: - if line: - if (len(msg) + len(line) + 1) < MAX_MESSAGE_LENGTH: - msg += line + '\n' - else: - self._send_msg(msg.format(**r)) - msg = "*Trade ID:* `{trade_id}` - continued\n" + line + '\n' - - self._send_msg(msg.format(**r)) + self.__send_status_msg(lines, r) except RPCException as e: self._send_msg(str(e)) + def __send_status_msg(self, lines: List[str], r: Dict[str, Any]) -> None: + """ + Send status message. + """ + msg = '' + + for line in lines: + if line: + if (len(msg) + len(line) + 1) < MAX_MESSAGE_LENGTH: + msg += line + '\n' + else: + self._send_msg(msg.format(**r)) + msg = "*Trade ID:* `{trade_id}` - continued\n" + line + '\n' + + self._send_msg(msg.format(**r)) + @authorized_only def _status_table(self, update: Update, context: CallbackContext) -> None: """ From 45d68222a177e62b81fd5d760e17cbf9614aa36a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Aug 2022 13:18:40 +0200 Subject: [PATCH 195/220] Reduce verbosity of Fiat Converter --- freqtrade/rpc/fiat_convert.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/freqtrade/rpc/fiat_convert.py b/freqtrade/rpc/fiat_convert.py index df33693ac..cbe4c0045 100644 --- a/freqtrade/rpc/fiat_convert.py +++ b/freqtrade/rpc/fiat_convert.py @@ -12,6 +12,7 @@ from pycoingecko import CoinGeckoAPI from requests.exceptions import RequestException from freqtrade.constants import SUPPORTED_FIAT +from freqtrade.mixins.logging_mixin import LoggingMixin logger = logging.getLogger(__name__) @@ -27,7 +28,7 @@ coingecko_mapping = { } -class CryptoToFiatConverter: +class CryptoToFiatConverter(LoggingMixin): """ Main class to initiate Crypto to FIAT. This object contains a list of pair Crypto, FIAT @@ -54,6 +55,7 @@ class CryptoToFiatConverter: # Timeout: 6h self._pair_price: TTLCache = TTLCache(maxsize=500, ttl=6 * 60 * 60) + LoggingMixin.__init__(self, logger, 3600) self._load_cryptomap() def _load_cryptomap(self) -> None: @@ -177,7 +179,9 @@ class CryptoToFiatConverter: if not _gekko_id: # return 0 for unsupported stake currencies (fiat-convert should not break the bot) - logger.warning("unsupported crypto-symbol %s - returning 0.0", crypto_symbol) + self.log_once( + f"unsupported crypto-symbol {crypto_symbol.upper()} - returning 0.0", + logger.warning) return 0.0 try: From 5250189f77bcc4c6c017fdcc3a60ae2a6104f714 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Aug 2022 15:08:13 +0200 Subject: [PATCH 196/220] Add Rollback function to Trade simplifies Session work --- freqtrade/persistence/trade_model.py | 6 +++++- freqtrade/rpc/api_server/deps.py | 4 ++-- freqtrade/rpc/rpc.py | 2 +- freqtrade/rpc/telegram.py | 2 +- tests/test_persistence.py | 1 + 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index 19d9361b6..3ea6ddf2d 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -196,7 +196,7 @@ class Order(_DECL_BASE): if filtered_orders: oobj = filtered_orders[0] oobj.update_from_ccxt_object(order) - Order.query.session.commit() + Trade.commit() else: logger.warning(f"Did not find order for {order}.") @@ -1148,6 +1148,10 @@ class Trade(_DECL_BASE, LocalTrade): def commit(): Trade.query.session.commit() + @staticmethod + def rollback(): + Trade.query.session.rollback() + @staticmethod def get_trades_proxy(*, pair: str = None, is_open: bool = None, open_date: datetime = None, close_date: datetime = None, diff --git a/freqtrade/rpc/api_server/deps.py b/freqtrade/rpc/api_server/deps.py index 81c013efa..66654c0b1 100644 --- a/freqtrade/rpc/api_server/deps.py +++ b/freqtrade/rpc/api_server/deps.py @@ -18,9 +18,9 @@ def get_rpc_optional() -> Optional[RPC]: def get_rpc() -> Optional[Iterator[RPC]]: _rpc = get_rpc_optional() if _rpc: - Trade.query.session.rollback() + Trade.rollback() yield _rpc - Trade.query.session.rollback() + Trade.rollback() else: raise RPCException('Bot is not in the correct state') diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 7e431ece9..d848da546 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -876,7 +876,7 @@ class RPC: lock.active = False lock.lock_end_time = datetime.now(timezone.utc) - PairLock.query.session.commit() + Trade.commit() return self._rpc_locks() diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 02fb5b4ee..9e0cd7d86 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -70,7 +70,7 @@ def authorized_only(command_handler: Callable[..., None]) -> Callable[..., Any]: ) return wrapper # Rollback session to avoid getting data stored in a transaction. - Trade.query.session.rollback() + Trade.rollback() logger.debug( 'Executing handler: %s for chat_id: %s', command_handler.__name__, diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 42fcc7413..eea6d6fa1 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -2375,6 +2375,7 @@ def test_Trade_object_idem(): 'delete', 'session', 'commit', + 'rollback', 'query', 'open_date', 'get_best_pair', From bfa859e6188b60fb95cf14429b2bd5189f18902d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Aug 2022 17:45:18 +0200 Subject: [PATCH 197/220] Remove unnecessary method (simplify) --- freqtrade/freqtradebot.py | 6 +++--- freqtrade/persistence/__init__.py | 2 +- freqtrade/persistence/models.py | 8 -------- tests/test_freqtradebot.py | 2 +- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 657e0bd82..390c8e8f6 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -26,7 +26,7 @@ from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange.exchange import timeframe_to_next_date from freqtrade.misc import safe_value_fallback, safe_value_fallback2 from freqtrade.mixins import LoggingMixin -from freqtrade.persistence import Order, PairLocks, Trade, cleanup_db, init_db +from freqtrade.persistence import Order, PairLocks, Trade, init_db from freqtrade.plugins.pairlistmanager import PairListManager from freqtrade.plugins.protectionmanager import ProtectionManager from freqtrade.resolvers import ExchangeResolver, StrategyResolver @@ -150,7 +150,7 @@ class FreqtradeBot(LoggingMixin): self.check_for_open_trades() self.rpc.cleanup() - cleanup_db() + Trade.commit() self.exchange.close() def startup(self) -> None: @@ -1701,7 +1701,6 @@ class FreqtradeBot(LoggingMixin): self.handle_order_fee(trade, order_obj, order) trade.update_trade(order_obj) - Trade.commit() if order.get('status') in constants.NON_OPEN_EXCHANGE_STATES: # If a entry order was closed, force update on stoploss on exchange @@ -1725,6 +1724,7 @@ class FreqtradeBot(LoggingMixin): # Updating wallets when order is closed self.wallets.update() + Trade.commit() self.order_close_notify(trade, order_obj, stoploss_order, send_msg) diff --git a/freqtrade/persistence/__init__.py b/freqtrade/persistence/__init__.py index f4e7470a7..9e1a7e922 100644 --- a/freqtrade/persistence/__init__.py +++ b/freqtrade/persistence/__init__.py @@ -1,5 +1,5 @@ # flake8: noqa: F401 -from freqtrade.persistence.models import cleanup_db, init_db +from freqtrade.persistence.models import init_db from freqtrade.persistence.pairlock_middleware import PairLocks from freqtrade.persistence.trade_model import LocalTrade, Order, Trade diff --git a/freqtrade/persistence/models.py b/freqtrade/persistence/models.py index 86d2f9f9c..f0fa05343 100644 --- a/freqtrade/persistence/models.py +++ b/freqtrade/persistence/models.py @@ -61,11 +61,3 @@ def init_db(db_url: str) -> None: previous_tables = inspect(engine).get_table_names() _DECL_BASE.metadata.create_all(engine) check_migrate(engine, decl_base=_DECL_BASE, previous_tables=previous_tables) - - -def cleanup_db() -> None: - """ - Flushes all pending operations to disk. - :return: None - """ - Trade.commit() diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 0b073a062..f274e2119 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -75,7 +75,7 @@ def test_process_calls_sendmsg(mocker, default_conf_usdt) -> None: def test_bot_cleanup(mocker, default_conf_usdt, caplog) -> None: - mock_cleanup = mocker.patch('freqtrade.freqtradebot.cleanup_db') + mock_cleanup = mocker.patch('freqtrade.freqtradebot.Trade.commit') coo_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cancel_all_open_orders') freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade.cleanup() From 78e129034ee64cc60e2975a70338767d7206dc73 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Aug 2022 17:59:08 +0200 Subject: [PATCH 198/220] Update docs to specify trading limit behaviour closes #7183 --- docs/backtesting.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/backtesting.md b/docs/backtesting.md index 50fc96923..a7baf6932 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -514,6 +514,7 @@ You can then load the trades to perform further analysis as shown in the [data a Since backtesting lacks some detailed information about what happens within a candle, it needs to take a few assumptions: +- Exchange [trading limits](#trading-limits-in-backtesting) are respected - Buys happen at open-price - All orders are filled at the requested price (no slippage, no unfilled orders) - Exit-signal exits happen at open-price of the consecutive candle @@ -543,7 +544,24 @@ Also, keep in mind that past results don't guarantee future success. In addition to the above assumptions, strategy authors should carefully read the [Common Mistakes](strategy-customization.md#common-mistakes-when-developing-strategies) section, to avoid using data in backtesting which is not available in real market conditions. -### Improved backtest accuracy +### Trading limits in backtesting + +Exchanges have certain trading limits, like minimum base currency, or minimum stake (quote) currency. +These limits are usually listed in the exchange documentation as "trading rules" or similar. + +Backtesting (as well as live and dry-run) does honor these limits, and will ensure that a stoploss can be placed below this value - so the value will be slightly higher than what the exchange specifies. +Freqtrade has however no information about historic limits. + +This can lead to situations where trading-limits are inflated by using a historic price, resulting in minimum amounts > 50$. + +For example: + +BTC minimum tradable amount is 0.001. +BTC trades at 22.000\$ today (0.001 BTC is related to this) - but the backtesting period includes prices as high as 50.000\$. +Today's minimum would be `0.001 * 22_000` - or 22\$. +However the limit could also be 50$ - based on `0.001 * 50_000` in some historic setting. + +## Improved backtest accuracy One big limitation of backtesting is it's inability to know how prices moved intra-candle (was high before close, or viceversa?). So assuming you run backtesting with a 1h timeframe, there will be 4 prices for that candle (Open, High, Low, Close). From 82aecc81f393e98b86115e9bdfa46dac1a143fad Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 2 Aug 2022 19:53:10 +0200 Subject: [PATCH 199/220] Accept parameters to forceexit --- freqtrade/rpc/api_server/api_schemas.py | 1 + freqtrade/rpc/api_server/api_v1.py | 2 +- freqtrade/rpc/rpc.py | 22 +++++++++++++++++----- scripts/rest_client.py | 10 ++++++++-- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index 333f2fe6e..d2a584136 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -330,6 +330,7 @@ class ForceEnterPayload(BaseModel): class ForceExitPayload(BaseModel): tradeid: str ordertype: Optional[OrderTypeValues] + amount: Optional[float] class BlacklistPayload(BaseModel): diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index b3506409d..29e4fb75a 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -161,7 +161,7 @@ def force_entry(payload: ForceEnterPayload, rpc: RPC = Depends(get_rpc)): @router.post('/forcesell', response_model=ResultMsg, tags=['trading']) def forceexit(payload: ForceExitPayload, rpc: RPC = Depends(get_rpc)): ordertype = payload.ordertype.value if payload.ordertype else None - return rpc._rpc_force_exit(payload.tradeid, ordertype) + return rpc._rpc_force_exit(payload.tradeid, ordertype, amount=payload.amount) @router.get('/blacklist', response_model=BlacklistResponse, tags=['info', 'pairlist']) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index d848da546..340adea43 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -660,12 +660,15 @@ class RPC: return {'status': 'No more buy will occur from now. Run /reload_config to reset.'} - def _rpc_force_exit(self, trade_id: str, ordertype: Optional[str] = None) -> Dict[str, str]: + def _rpc_force_exit(self, trade_id: str, ordertype: Optional[str] = None, *, + amount: Optional[float]) -> Dict[str, str]: """ Handler for forceexit . Sells the given trade at current price """ - def _exec_force_exit(trade: Trade) -> None: + + def _exec_force_exit(trade: Trade, ordertype: Optional[str], + _amount: Optional[float] = None) -> None: # Check if there is there is an open order fully_canceled = False if trade.open_order_id: @@ -686,10 +689,19 @@ class RPC: exit_check = ExitCheckTuple(exit_type=ExitType.FORCE_EXIT) order_type = ordertype or self._freqtrade.strategy.order_types.get( "force_exit", self._freqtrade.strategy.order_types["exit"]) + sub_amount: float = None + if _amount and _amount < trade.amount: + # Partial exit ... + min_exit_stake = self._freqtrade.exchange.get_min_pair_stake_amount( + trade.pair, current_rate, trade.stop_loss_pct) + remaining = (trade.amount - _amount) * current_rate + if remaining < min_exit_stake: + raise RPCException(f'Remaining amount of {remaining} would be too small.') + sub_amount = _amount self._freqtrade.execute_trade_exit( - trade, current_rate, exit_check, ordertype=order_type) - # ---- EOF def _exec_forcesell ---- + trade, current_rate, exit_check, ordertype=order_type, + sub_trade_amt=sub_amount) if self._freqtrade.state != State.RUNNING: raise RPCException('trader is not running') @@ -711,7 +723,7 @@ class RPC: logger.warning('force_exit: Invalid argument received') raise RPCException('invalid argument') - _exec_force_exit(trade) + _exec_force_exit(trade, ordertype, amount) Trade.commit() self._freqtrade.wallets.update() return {'result': f'Created sell order for trade {trade_id}.'} diff --git a/scripts/rest_client.py b/scripts/rest_client.py index e5d358c98..989e6a50d 100755 --- a/scripts/rest_client.py +++ b/scripts/rest_client.py @@ -275,14 +275,20 @@ class FtRestClient(): } return self._post("forceenter", data=data) - def forceexit(self, tradeid): + def forceexit(self, tradeid, ordertype=None, amount=None): """Force-exit a trade. :param tradeid: Id of the trade (can be received via status command) + :param ordertype: Order type to use (must be market or limit) + :param amount: Amount to sell. Full sell if not given :return: json object """ - return self._post("forceexit", data={"tradeid": tradeid}) + return self._post("forceexit", data={ + "tradeid": tradeid, + "ordertype": ordertype, + "amount": amount, + }) def strategies(self): """Lists available strategies From daf015d0077736ba94c0b3cc3302942c425a9357 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 2 Aug 2022 19:54:37 +0200 Subject: [PATCH 200/220] extract nested force_exit function to private instance function --- freqtrade/rpc/rpc.py | 76 ++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 340adea43..36327f091 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -660,6 +660,42 @@ class RPC: return {'status': 'No more buy will occur from now. Run /reload_config to reset.'} + def __exec_force_exit(self, trade: Trade, ordertype: Optional[str], + _amount: Optional[float] = None) -> None: + # Check if there is there is an open order + fully_canceled = False + if trade.open_order_id: + order = self._freqtrade.exchange.fetch_order(trade.open_order_id, trade.pair) + + if order['side'] == trade.entry_side: + fully_canceled = self._freqtrade.handle_cancel_enter( + trade, order, CANCEL_REASON['FORCE_EXIT']) + + if order['side'] == trade.exit_side: + # Cancel order - so it is placed anew with a fresh price. + self._freqtrade.handle_cancel_exit(trade, order, CANCEL_REASON['FORCE_EXIT']) + + if not fully_canceled: + # Get current rate and execute sell + current_rate = self._freqtrade.exchange.get_rate( + trade.pair, side='exit', is_short=trade.is_short, refresh=True) + exit_check = ExitCheckTuple(exit_type=ExitType.FORCE_EXIT) + order_type = ordertype or self._freqtrade.strategy.order_types.get( + "force_exit", self._freqtrade.strategy.order_types["exit"]) + sub_amount: float = None + if _amount and _amount < trade.amount: + # Partial exit ... + min_exit_stake = self._freqtrade.exchange.get_min_pair_stake_amount( + trade.pair, current_rate, trade.stop_loss_pct) + remaining = (trade.amount - _amount) * current_rate + if remaining < min_exit_stake: + raise RPCException(f'Remaining amount of {remaining} would be too small.') + sub_amount = _amount + + self._freqtrade.execute_trade_exit( + trade, current_rate, exit_check, ordertype=order_type, + sub_trade_amt=sub_amount) + def _rpc_force_exit(self, trade_id: str, ordertype: Optional[str] = None, *, amount: Optional[float]) -> Dict[str, str]: """ @@ -667,42 +703,6 @@ class RPC: Sells the given trade at current price """ - def _exec_force_exit(trade: Trade, ordertype: Optional[str], - _amount: Optional[float] = None) -> None: - # Check if there is there is an open order - fully_canceled = False - if trade.open_order_id: - order = self._freqtrade.exchange.fetch_order(trade.open_order_id, trade.pair) - - if order['side'] == trade.entry_side: - fully_canceled = self._freqtrade.handle_cancel_enter( - trade, order, CANCEL_REASON['FORCE_EXIT']) - - if order['side'] == trade.exit_side: - # Cancel order - so it is placed anew with a fresh price. - self._freqtrade.handle_cancel_exit(trade, order, CANCEL_REASON['FORCE_EXIT']) - - if not fully_canceled: - # Get current rate and execute sell - current_rate = self._freqtrade.exchange.get_rate( - trade.pair, side='exit', is_short=trade.is_short, refresh=True) - exit_check = ExitCheckTuple(exit_type=ExitType.FORCE_EXIT) - order_type = ordertype or self._freqtrade.strategy.order_types.get( - "force_exit", self._freqtrade.strategy.order_types["exit"]) - sub_amount: float = None - if _amount and _amount < trade.amount: - # Partial exit ... - min_exit_stake = self._freqtrade.exchange.get_min_pair_stake_amount( - trade.pair, current_rate, trade.stop_loss_pct) - remaining = (trade.amount - _amount) * current_rate - if remaining < min_exit_stake: - raise RPCException(f'Remaining amount of {remaining} would be too small.') - sub_amount = _amount - - self._freqtrade.execute_trade_exit( - trade, current_rate, exit_check, ordertype=order_type, - sub_trade_amt=sub_amount) - if self._freqtrade.state != State.RUNNING: raise RPCException('trader is not running') @@ -710,7 +710,7 @@ class RPC: if trade_id == 'all': # Execute sell for all open orders for trade in Trade.get_open_trades(): - _exec_force_exit(trade) + self.__exec_force_exit(trade) Trade.commit() self._freqtrade.wallets.update() return {'result': 'Created sell orders for all open trades.'} @@ -723,7 +723,7 @@ class RPC: logger.warning('force_exit: Invalid argument received') raise RPCException('invalid argument') - _exec_force_exit(trade, ordertype, amount) + self.__exec_force_exit(trade, ordertype, amount) Trade.commit() self._freqtrade.wallets.update() return {'result': f'Created sell order for trade {trade_id}.'} From eff8cd7ecbf2da8aea10a363a98aafa5f0bec480 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 2 Aug 2022 20:15:47 +0200 Subject: [PATCH 201/220] Add leverage to force_entry --- freqtrade/freqtradebot.py | 27 +++++++++++++++---------- freqtrade/rpc/api_server/api_schemas.py | 1 + freqtrade/rpc/api_server/api_v1.py | 10 ++++----- freqtrade/rpc/rpc.py | 4 +++- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 390c8e8f6..0dbeb2e44 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -624,7 +624,8 @@ class FreqtradeBot(LoggingMixin): ordertype: Optional[str] = None, enter_tag: Optional[str] = None, trade: Optional[Trade] = None, - order_adjust: bool = False + order_adjust: bool = False, + leverage_: Optional[float] = None, ) -> bool: """ Executes a limit buy for the given pair @@ -640,7 +641,7 @@ class FreqtradeBot(LoggingMixin): pos_adjust = trade is not None enter_limit_requested, stake_amount, leverage = self.get_valid_enter_price_and_stake( - pair, price, stake_amount, trade_side, enter_tag, trade, order_adjust) + pair, price, stake_amount, trade_side, enter_tag, trade, order_adjust, leverage_) if not stake_amount: return False @@ -787,6 +788,7 @@ class FreqtradeBot(LoggingMixin): entry_tag: Optional[str], trade: Optional[Trade], order_adjust: bool, + leverage_: Optional[float], ) -> Tuple[float, float, float]: if price: @@ -809,16 +811,19 @@ class FreqtradeBot(LoggingMixin): if not enter_limit_requested: raise PricingError('Could not determine entry price.') - if trade is None: + if self.trading_mode != TradingMode.SPOT and trade is None: max_leverage = self.exchange.get_max_leverage(pair, stake_amount) - leverage = strategy_safe_wrapper(self.strategy.leverage, default_retval=1.0)( - pair=pair, - current_time=datetime.now(timezone.utc), - current_rate=enter_limit_requested, - proposed_leverage=1.0, - max_leverage=max_leverage, - side=trade_side, entry_tag=entry_tag, - ) if self.trading_mode != TradingMode.SPOT else 1.0 + if leverage_: + leverage = leverage_ + else: + leverage = strategy_safe_wrapper(self.strategy.leverage, default_retval=1.0)( + pair=pair, + current_time=datetime.now(timezone.utc), + current_rate=enter_limit_requested, + proposed_leverage=1.0, + max_leverage=max_leverage, + side=trade_side, entry_tag=entry_tag, + ) # Cap leverage between 1.0 and max_leverage. leverage = min(max(leverage, 1.0), max_leverage) else: diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index d2a584136..1641df384 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -325,6 +325,7 @@ class ForceEnterPayload(BaseModel): ordertype: Optional[OrderTypeValues] stakeamount: Optional[float] entry_tag: Optional[str] + leverage: Optional[float] class ForceExitPayload(BaseModel): diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index 29e4fb75a..54d7baf38 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -37,7 +37,8 @@ logger = logging.getLogger(__name__) # 2.14: Add entry/exit orders to trade response # 2.15: Add backtest history endpoints # 2.16: Additional daily metrics -API_VERSION = 2.16 +# 2.16: Forceentry - leverage, partial force_exit +API_VERSION = 2.17 # Public API, requires no auth. router_public = APIRouter() @@ -142,12 +143,11 @@ def show_config(rpc: Optional[RPC] = Depends(get_rpc_optional), config=Depends(g @router.post('/forcebuy', response_model=ForceEnterResponse, tags=['trading']) def force_entry(payload: ForceEnterPayload, rpc: RPC = Depends(get_rpc)): ordertype = payload.ordertype.value if payload.ordertype else None - stake_amount = payload.stakeamount if payload.stakeamount else None - entry_tag = payload.entry_tag if payload.entry_tag else 'force_entry' trade = rpc._rpc_force_entry(payload.pair, payload.price, order_side=payload.side, - order_type=ordertype, stake_amount=stake_amount, - enter_tag=entry_tag) + order_type=ordertype, stake_amount=payload.stakeamount, + enter_tag=payload.entry_tag or 'force_entry', + leverage=payload.leverage) if trade: return ForceEnterResponse.parse_obj(trade.to_json()) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 36327f091..22effb849 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -732,7 +732,8 @@ class RPC: order_type: Optional[str] = None, order_side: SignalDirection = SignalDirection.LONG, stake_amount: Optional[float] = None, - enter_tag: Optional[str] = 'force_entry') -> Optional[Trade]: + enter_tag: Optional[str] = 'force_entry', + leverage: Optional[float] = None) -> Optional[Trade]: """ Handler for forcebuy Buys a pair trade at the given or current price @@ -774,6 +775,7 @@ class RPC: ordertype=order_type, trade=trade, is_short=is_short, enter_tag=enter_tag, + leverage_=leverage, ): Trade.commit() trade = Trade.get_trades([Trade.is_open.is_(True), Trade.pair == pair]).first() From d1998f7ed0bf2f58daf439d367fa25b7319f3aa1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 2 Aug 2022 20:16:01 +0200 Subject: [PATCH 202/220] Fix forceexit calling --- freqtrade/rpc/rpc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 22effb849..7694b2414 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -697,7 +697,7 @@ class RPC: sub_trade_amt=sub_amount) def _rpc_force_exit(self, trade_id: str, ordertype: Optional[str] = None, *, - amount: Optional[float]) -> Dict[str, str]: + amount: Optional[float] = None) -> Dict[str, str]: """ Handler for forceexit . Sells the given trade at current price @@ -710,7 +710,7 @@ class RPC: if trade_id == 'all': # Execute sell for all open orders for trade in Trade.get_open_trades(): - self.__exec_force_exit(trade) + self.__exec_force_exit(trade, ordertype) Trade.commit() self._freqtrade.wallets.update() return {'result': 'Created sell orders for all open trades.'} From d3780b931c27a6cdede7d58d5814de7d1aa8ac05 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 2 Aug 2022 20:21:02 +0200 Subject: [PATCH 203/220] Add test passing leverage to execute_entry --- tests/test_freqtradebot.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index f274e2119..fb5fd38d8 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -973,6 +973,14 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, trade.is_short = is_short assert pytest.approx(trade.stake_amount) == 500 + order['id'] = '55673' + + freqtrade.strategy.leverage.reset_mock() + assert freqtrade.execute_entry(pair, 200, leverage_=3) + assert freqtrade.strategy.leverage.call_count == 0 + trade = Trade.query.all()[10] + assert trade.leverage == 1 if trading_mode == 'spot' else 3 + @pytest.mark.parametrize("is_short", [False, True]) def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_order, is_short) -> None: From 6ded2d5b7c442a5fd69d56ee63361df4f4a3db7e Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Aug 2022 16:28:36 +0200 Subject: [PATCH 204/220] Improve forceexit API test --- freqtrade/rpc/rpc.py | 2 +- tests/conftest_trades.py | 6 ++++-- tests/rpc/test_rpc_apiserver.py | 23 +++++++++++++++++++---- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 7694b2414..cda4fdc22 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -682,7 +682,7 @@ class RPC: exit_check = ExitCheckTuple(exit_type=ExitType.FORCE_EXIT) order_type = ordertype or self._freqtrade.strategy.order_types.get( "force_exit", self._freqtrade.strategy.order_types["exit"]) - sub_amount: float = None + sub_amount: Optional[float] = None if _amount and _amount < trade.amount: # Partial exit ... min_exit_stake = self._freqtrade.exchange.get_min_pair_stake_amount( diff --git a/tests/conftest_trades.py b/tests/conftest_trades.py index 1a8cf3183..9642435e5 100644 --- a/tests/conftest_trades.py +++ b/tests/conftest_trades.py @@ -214,7 +214,8 @@ def mock_trade_4(fee, is_short: bool): open_order_id=f'prod_buy_{direc(is_short)}_12345', strategy='StrategyTestV3', timeframe=5, - is_short=is_short + is_short=is_short, + stop_loss_pct=0.10 ) o = Order.parse_from_ccxt_object(mock_order_4(is_short), 'ETC/BTC', entry_side(is_short)) trade.orders.append(o) @@ -270,7 +271,8 @@ def mock_trade_5(fee, is_short: bool): enter_tag='TEST1', stoploss_order_id=f'prod_stoploss_{direc(is_short)}_3455', timeframe=5, - is_short=is_short + is_short=is_short, + stop_loss_pct=0.10, ) o = Order.parse_from_ccxt_object(mock_order_5(is_short), 'XRP/BTC', entry_side(is_short)) trade.orders.append(o) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index b7161e680..d2d9a73d5 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1202,7 +1202,7 @@ def test_api_forceexit(botclient, mocker, ticker, fee, markets): fetch_ticker=ticker, get_fee=fee, markets=PropertyMock(return_value=markets), - _is_dry_limit_order_filled=MagicMock(return_value=False), + _is_dry_limit_order_filled=MagicMock(return_value=True), ) patch_get_signal(ftbot) @@ -1212,12 +1212,27 @@ def test_api_forceexit(botclient, mocker, ticker, fee, markets): assert rc.json() == {"error": "Error querying /api/v1/forceexit: invalid argument"} Trade.query.session.rollback() - ftbot.enter_positions() + create_mock_trades(fee) + trade = Trade.get_trades([Trade.id == 5]).first() + assert pytest.approx(trade.amount) == 123 + 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.'} + Trade.query.session.rollback() + + trade = Trade.get_trades([Trade.id == 5]).first() + assert pytest.approx(trade.amount) == 100 + assert trade.is_open is True rc = client_post(client, f"{BASE_URI}/forceexit", - data='{"tradeid": "1"}') + data='{"tradeid": "5"}') assert_response(rc) - assert rc.json() == {'result': 'Created sell order for trade 1.'} + assert rc.json() == {'result': 'Created sell order for trade 5.'} + Trade.query.session.rollback() + + trade = Trade.get_trades([Trade.id == 5]).first() + assert trade.is_open is False def test_api_pair_candles(botclient, ohlcv_history): From 5182f755f1aa67bae976c5314e0a3fb2ab970662 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 7 Aug 2022 10:08:35 +0200 Subject: [PATCH 205/220] Add debug setup documentation closes #7167 --- docs/developer.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/developer.md b/docs/developer.md index 0209d220a..aca4ce4ed 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -68,6 +68,36 @@ def test_method_to_test(caplog): ``` +### Debug configuration + +To debug freqtrade, we recommend VSCode with the following launch configuration (located in `.vscode/launch.json`). +Details will obviously vary between setups - but this should work to get you started. + +``` json +{ + "name": "freqtrade trade", + "type": "python", + "request": "launch", + "module": "freqtrade", + "console": "integratedTerminal", + "args": [ + "trade", + // Optional: + // "--userdir", "user_data", + "--strategy", + "MyAwesomeStrategy", + ] +}, +``` + +Command line arguments can be added in the `"args"` array. +This method can also be used to debug a strategy, by setting the breakpoints within the strategy. + +A similar setup can also be taken for Pycharm - using `freqtrade` as module name, and setting the command line arguments as "parameters". + +!!! Note "Startup directory" + This assumes that you have the repository checked out, and the editor is started at the repository root level (so setup.py is at the top level of your repository). + ## ErrorHandling Freqtrade Exceptions all inherit from `FreqtradeException`. From 0b2104fc7a13e8034e051cf456dce25b30097f4a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 7 Aug 2022 10:13:22 +0200 Subject: [PATCH 206/220] Properly increment the api version --- freqtrade/rpc/api_server/api_v1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index 54d7baf38..e0fef7be8 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -37,7 +37,7 @@ logger = logging.getLogger(__name__) # 2.14: Add entry/exit orders to trade response # 2.15: Add backtest history endpoints # 2.16: Additional daily metrics -# 2.16: Forceentry - leverage, partial force_exit +# 2.17: Forceentry - leverage, partial force_exit API_VERSION = 2.17 # Public API, requires no auth. From e48e82232d67695d412ba89df7dcea725a991f3d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 7 Aug 2022 10:42:56 +0200 Subject: [PATCH 207/220] Force response API to js to fix faulty system configs closes #7147 --- freqtrade/rpc/api_server/web_ui.py | 7 ++++++- tests/rpc/test_rpc_apiserver.py | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/api_server/web_ui.py b/freqtrade/rpc/api_server/web_ui.py index b04269c61..e1a277b30 100644 --- a/freqtrade/rpc/api_server/web_ui.py +++ b/freqtrade/rpc/api_server/web_ui.py @@ -1,4 +1,5 @@ from pathlib import Path +from typing import Optional from fastapi import APIRouter from fastapi.exceptions import HTTPException @@ -50,8 +51,12 @@ async def index_html(rest_of_path: str): filename = uibase / rest_of_path # It's security relevant to check "relative_to". # Without this, Directory-traversal is possible. + media_type: Optional[str] = None + if filename.suffix == '.js': + # Force text/javascript for .js files - Circumvent faulty system configuration + media_type = 'application/javascript' if filename.is_file() and is_relative_to(filename, uibase): - return FileResponse(str(filename)) + return FileResponse(str(filename), media_type=media_type) index_file = uibase / 'index.html' if not index_file.is_file(): diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index b7161e680..6bbf3cff6 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -109,6 +109,9 @@ def test_api_ui_fallback(botclient, mocker): rc = client_get(client, "/something") assert rc.status_code == 200 + rc = client_get(client, "/something.js") + assert rc.status_code == 200 + # Test directory traversal without mock rc = client_get(client, '%2F%2F%2Fetc/passwd') assert rc.status_code == 200 From 11a2eb6cc5598f837478864fba9139b78a1603db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Aug 2022 03:01:16 +0000 Subject: [PATCH 208/220] Bump flake8 from 5.0.1 to 5.0.4 Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.1 to 5.0.4. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/5.0.1...5.0.4) --- updated-dependencies: - dependency-name: flake8 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 79021e591..16fc1b046 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,7 +5,7 @@ -r docs/requirements-docs.txt coveralls==3.3.1 -flake8==5.0.1 +flake8==5.0.4 flake8-tidy-imports==4.8.0 mypy==0.971 pre-commit==2.20.0 From 7fd3f98ae8e730d964b10260e604d6b45592176a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Aug 2022 03:01:20 +0000 Subject: [PATCH 209/220] Bump scikit-learn from 1.1.1 to 1.1.2 Bumps [scikit-learn](https://github.com/scikit-learn/scikit-learn) from 1.1.1 to 1.1.2. - [Release notes](https://github.com/scikit-learn/scikit-learn/releases) - [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.1.1...1.1.2) --- updated-dependencies: - dependency-name: scikit-learn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-hyperopt.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-hyperopt.txt b/requirements-hyperopt.txt index cc659fc50..11b9511f2 100644 --- a/requirements-hyperopt.txt +++ b/requirements-hyperopt.txt @@ -3,7 +3,7 @@ # Required for hyperopt scipy==1.9.0 -scikit-learn==1.1.1 +scikit-learn==1.1.2 scikit-optimize==0.9.0 filelock==3.7.1 progressbar2==4.0.0 From a45a35f38c616acf2565816163d2f2bf50e15d84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Aug 2022 03:01:25 +0000 Subject: [PATCH 210/220] Bump jsonschema from 4.9.0 to 4.9.1 Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.9.0 to 4.9.1. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.9.0...v4.9.1) --- updated-dependencies: - dependency-name: jsonschema 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 4cb6519b3..202ded414 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ arrow==1.2.2 cachetools==4.2.2 requests==2.28.1 urllib3==1.26.11 -jsonschema==4.9.0 +jsonschema==4.9.1 TA-Lib==0.4.24 technical==1.3.0 tabulate==0.8.10 From 97c077171ac63b16839baf0651d8e526e02a8d88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Aug 2022 03:01:28 +0000 Subject: [PATCH 211/220] Bump types-requests from 2.28.6 to 2.28.8 Bumps [types-requests](https://github.com/python/typeshed) from 2.28.6 to 2.28.8. - [Release notes](https://github.com/python/typeshed/releases) - [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 79021e591..b0533d415 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,6 +24,6 @@ nbconvert==6.5.0 # mypy types types-cachetools==5.2.1 types-filelock==3.2.7 -types-requests==2.28.6 +types-requests==2.28.8 types-tabulate==0.8.11 types-python-dateutil==2.8.19 From 71c88244fedae929b9189d2560d6a8c9c9528cec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Aug 2022 03:01:38 +0000 Subject: [PATCH 212/220] Bump ccxt from 1.91.55 to 1.91.93 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.91.55 to 1.91.93. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.91.55...1.91.93) --- 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 4cb6519b3..93c41c4c9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.23.1 pandas==1.4.3 pandas-ta==0.3.14b -ccxt==1.91.55 +ccxt==1.91.93 # Pin cryptography for now due to rust build errors with piwheels cryptography==37.0.4 aiohttp==3.8.1 From 0c7d862aae1d1b44d57af0177578edd586bc49bb Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 8 Aug 2022 06:54:00 +0200 Subject: [PATCH 213/220] types-requests bump pre-commit --- .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 398d09875..a205f24ec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: additional_dependencies: - types-cachetools==5.2.1 - types-filelock==3.2.7 - - types-requests==2.28.6 + - types-requests==2.28.8 - types-tabulate==0.8.11 - types-python-dateutil==2.8.19 # stages: [push] From b5c5a95b64f8c35b2606da65114d6c65d66ec758 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 9 Aug 2022 20:09:35 +0200 Subject: [PATCH 214/220] FTX: Use conditionalOrders endpoint to get proper stop-market order id closes #7165 --- freqtrade/exchange/ftx.py | 14 +++++++++++--- tests/exchange/test_ftx.py | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/freqtrade/exchange/ftx.py b/freqtrade/exchange/ftx.py index 9ee6894f1..b3c219542 100644 --- a/freqtrade/exchange/ftx.py +++ b/freqtrade/exchange/ftx.py @@ -1,6 +1,6 @@ """ FTX exchange subclass """ import logging -from typing import Any, Dict, List, Tuple +from typing import Any, Dict, List, Optional, Tuple import ccxt @@ -116,9 +116,17 @@ class Ftx(Exchange): if len(order) == 1: if order[0].get('status') == 'closed': # Trigger order was triggered ... - real_order_id = order[0].get('info', {}).get('orderId') + real_order_id: Optional[str] = order[0].get('info', {}).get('orderId') # OrderId may be None for stoploss-market orders - # But contains "average" in these cases. + # So we need to get it through the endpoint + # /conditional_orders/{conditional_order_id}/triggers + if not real_order_id: + res = self._api.privateGetConditionalOrdersConditionalOrderIdTriggers( + params={'conditional_order_id': order_id}) + self._log_exchange_response('fetch_stoploss_order2', res) + real_order_id = res['result'][0]['orderId'] if res.get( + 'result', []) else None + if real_order_id: order1 = self._api.fetch_order(real_order_id, pair) self._log_exchange_response('fetch_stoploss_order1', order1) diff --git a/tests/exchange/test_ftx.py b/tests/exchange/test_ftx.py index 5a83b964a..5213c1b36 100644 --- a/tests/exchange/test_ftx.py +++ b/tests/exchange/test_ftx.py @@ -203,7 +203,7 @@ def test_fetch_stoploss_order_ftx(default_conf, mocker, limit_sell_order, limit_ 'info': { 'orderId': 'mocked_limit_sell', }}]) - api_mock.fetch_order = MagicMock(return_value=limit_sell_order) + api_mock.fetch_order = MagicMock(return_value=limit_sell_order.copy()) # No orderId field - no call to fetch_order resp = exchange.fetch_stoploss_order('X', 'TKN/BTC') @@ -219,11 +219,23 @@ def test_fetch_stoploss_order_ftx(default_conf, mocker, limit_sell_order, limit_ order = {'id': 'X', 'status': 'closed', 'info': {'orderId': None}, 'average': 0.254} api_mock.fetch_orders = MagicMock(return_value=[order]) api_mock.fetch_order.reset_mock() + api_mock.privateGetConditionalOrdersConditionalOrderIdTriggers = MagicMock( + return_value={'result': [ + {'orderId': 'mocked_market_sell', 'type': 'market', 'side': 'sell', 'price': 0.254} + ]}) resp = exchange.fetch_stoploss_order('X', 'TKN/BTC') assert resp # fetch_order not called (no regular order ID) - assert api_mock.fetch_order.call_count == 0 - assert order == order + assert api_mock.fetch_order.call_count == 1 + api_mock.privateGetConditionalOrdersConditionalOrderIdTriggers.call_count == 1 + expected_resp = limit_sell_order.copy() + expected_resp.update({ + 'id_stop': 'X', + 'id': 'X', + 'type': 'stop', + 'status_stop': 'triggered', + }) + assert expected_resp == resp with pytest.raises(InvalidOrderException): api_mock.fetch_orders = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) From 736884c5a909b22a98428a2c2953413820d2840d Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 9 Aug 2022 20:43:58 +0200 Subject: [PATCH 215/220] Orders should be allowed to have empty fill/remaining values --- freqtrade/rpc/api_server/api_schemas.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index 333f2fe6e..8f4066ac7 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -194,11 +194,11 @@ class OrderSchema(BaseModel): pair: str order_id: str status: str - remaining: float + remaining: Optional[float] amount: float safe_price: float cost: float - filled: float + filled: Optional[float] ft_order_side: str order_type: str is_open: bool From ce2c9bf26dd54c5cee3864edf60fa496e5711922 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 10 Aug 2022 06:44:41 +0200 Subject: [PATCH 216/220] Slight renaming of variable --- freqtrade/rpc/rpc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index cda4fdc22..9f2c8cf37 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -661,7 +661,7 @@ class RPC: return {'status': 'No more buy will occur from now. Run /reload_config to reset.'} def __exec_force_exit(self, trade: Trade, ordertype: Optional[str], - _amount: Optional[float] = None) -> None: + amount: Optional[float] = None) -> None: # Check if there is there is an open order fully_canceled = False if trade.open_order_id: @@ -683,14 +683,14 @@ class RPC: order_type = ordertype or self._freqtrade.strategy.order_types.get( "force_exit", self._freqtrade.strategy.order_types["exit"]) sub_amount: Optional[float] = None - if _amount and _amount < trade.amount: + if amount and amount < trade.amount: # Partial exit ... min_exit_stake = self._freqtrade.exchange.get_min_pair_stake_amount( trade.pair, current_rate, trade.stop_loss_pct) - remaining = (trade.amount - _amount) * current_rate + remaining = (trade.amount - amount) * current_rate if remaining < min_exit_stake: raise RPCException(f'Remaining amount of {remaining} would be too small.') - sub_amount = _amount + sub_amount = amount self._freqtrade.execute_trade_exit( trade, current_rate, exit_check, ordertype=order_type, From 573964b19fc38daec4a8c8ce7387453c5eb03c01 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 10 Aug 2022 07:12:56 +0200 Subject: [PATCH 217/220] Dry Market orders should update "remaining" --- freqtrade/exchange/exchange.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index b6996211f..7eb71351e 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -849,6 +849,7 @@ class Exchange: dry_order.update({ 'average': average, 'filled': _amount, + 'remaining': 0.0, 'cost': (dry_order['amount'] * average) / leverage }) # market orders will always incurr taker fees From adc8ee88e2ec72aafe8c02af591127512dbf7ef8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 10 Aug 2022 08:57:19 +0000 Subject: [PATCH 218/220] Move periodicCache to Utils package --- freqtrade/configuration/__init__.py | 1 - freqtrade/data/dataprovider.py | 2 +- freqtrade/plugins/pairlist/AgeFilter.py | 2 +- freqtrade/util/__init__.py | 2 ++ .../{configuration/PeriodicCache.py => util/periodic_cache.py} | 0 tests/test_periodiccache.py | 2 +- 6 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 freqtrade/util/__init__.py rename freqtrade/{configuration/PeriodicCache.py => util/periodic_cache.py} (100%) diff --git a/freqtrade/configuration/__init__.py b/freqtrade/configuration/__init__.py index cf41c0ca9..730a4e47f 100644 --- a/freqtrade/configuration/__init__.py +++ b/freqtrade/configuration/__init__.py @@ -4,5 +4,4 @@ from freqtrade.configuration.check_exchange import check_exchange from freqtrade.configuration.config_setup import setup_utils_configuration from freqtrade.configuration.config_validation import validate_config_consistency from freqtrade.configuration.configuration import Configuration -from freqtrade.configuration.PeriodicCache import PeriodicCache from freqtrade.configuration.timerange import TimeRange diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index e21f10193..21cead77f 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -12,12 +12,12 @@ from typing import Any, Dict, List, Optional, Tuple from pandas import DataFrame from freqtrade.configuration import TimeRange -from freqtrade.configuration.PeriodicCache import PeriodicCache from freqtrade.constants import ListPairsWithTimeframes, PairWithTimeframe from freqtrade.data.history import load_pair_history from freqtrade.enums import CandleType, RunMode from freqtrade.exceptions import ExchangeError, OperationalException from freqtrade.exchange import Exchange, timeframe_to_seconds +from freqtrade.util import PeriodicCache logger = logging.getLogger(__name__) diff --git a/freqtrade/plugins/pairlist/AgeFilter.py b/freqtrade/plugins/pairlist/AgeFilter.py index 786f32e88..13c992c87 100644 --- a/freqtrade/plugins/pairlist/AgeFilter.py +++ b/freqtrade/plugins/pairlist/AgeFilter.py @@ -8,11 +8,11 @@ from typing import Any, Dict, List, Optional import arrow from pandas import DataFrame -from freqtrade.configuration import PeriodicCache from freqtrade.constants import ListPairsWithTimeframes from freqtrade.exceptions import OperationalException from freqtrade.misc import plural from freqtrade.plugins.pairlist.IPairList import IPairList +from freqtrade.util import PeriodicCache logger = logging.getLogger(__name__) diff --git a/freqtrade/util/__init__.py b/freqtrade/util/__init__.py new file mode 100644 index 000000000..fc4d66380 --- /dev/null +++ b/freqtrade/util/__init__.py @@ -0,0 +1,2 @@ +# flake8: noqa: F401 +from freqtrade.util.periodic_cache import PeriodicCache diff --git a/freqtrade/configuration/PeriodicCache.py b/freqtrade/util/periodic_cache.py similarity index 100% rename from freqtrade/configuration/PeriodicCache.py rename to freqtrade/util/periodic_cache.py diff --git a/tests/test_periodiccache.py b/tests/test_periodiccache.py index b2bd8ba2b..df05de4ef 100644 --- a/tests/test_periodiccache.py +++ b/tests/test_periodiccache.py @@ -1,6 +1,6 @@ import time_machine -from freqtrade.configuration import PeriodicCache +from freqtrade.util import PeriodicCache def test_ttl_cache(): From e7cb1b73753ad412d20e2cad58b76326c15e7ce7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 10 Aug 2022 11:26:06 +0000 Subject: [PATCH 219/220] Wrap Precise into FtPecise --- freqtrade/exchange/exchange.py | 9 ++--- freqtrade/util/__init__.py | 1 + freqtrade/util/ft_precise.py | 9 +++++ tests/exchange/test_ccxt_precise.py | 52 ++++++++++++++--------------- 4 files changed, 41 insertions(+), 30 deletions(-) create mode 100644 freqtrade/util/ft_precise.py diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 7eb71351e..2806a4f42 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -16,7 +16,7 @@ import arrow import ccxt import ccxt.async_support as ccxt_async from cachetools import TTLCache -from ccxt import ROUND_DOWN, ROUND_UP, TICK_SIZE, TRUNCATE, Precise, decimal_to_precision +from ccxt import ROUND_DOWN, ROUND_UP, TICK_SIZE, TRUNCATE, decimal_to_precision from pandas import DataFrame from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES, BuySell, @@ -32,6 +32,7 @@ from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, BAD_EXCHANGE retrier_async) from freqtrade.misc import chunks, deep_merge_dicts, safe_value_fallback2 from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist +from freqtrade.util import FtPrecise CcxtModuleType = Any @@ -708,10 +709,10 @@ class Exchange: # counting_mode=self.precisionMode, # )) if self.precisionMode == TICK_SIZE: - precision = Precise(str(self.markets[pair]['precision']['price'])) - price_str = Precise(str(price)) + precision = FtPrecise(str(self.markets[pair]['precision']['price'])) + price_str = FtPrecise(str(price)) missing = price_str % precision - if not missing == Precise("0"): + if not missing == FtPrecise("0"): price = round(float(str(price_str - missing + precision)), 14) else: symbol_prec = self.markets[pair]['precision']['price'] diff --git a/freqtrade/util/__init__.py b/freqtrade/util/__init__.py index fc4d66380..7980b7ca2 100644 --- a/freqtrade/util/__init__.py +++ b/freqtrade/util/__init__.py @@ -1,2 +1,3 @@ # flake8: noqa: F401 +from freqtrade.util.ft_precise import FtPrecise from freqtrade.util.periodic_cache import PeriodicCache diff --git a/freqtrade/util/ft_precise.py b/freqtrade/util/ft_precise.py new file mode 100644 index 000000000..9c79552c2 --- /dev/null +++ b/freqtrade/util/ft_precise.py @@ -0,0 +1,9 @@ +""" +Slim wrapper around ccxt's Precise (string math) +To have imports from freqtrade +""" +from ccxt import Precise + + +class FtPrecise(Precise): + pass diff --git a/tests/exchange/test_ccxt_precise.py b/tests/exchange/test_ccxt_precise.py index 026adb4c1..770dde13c 100644 --- a/tests/exchange/test_ccxt_precise.py +++ b/tests/exchange/test_ccxt_precise.py @@ -1,14 +1,14 @@ -from ccxt import Precise +from freqtrade.util import FtPrecise -ws = Precise('-1.123e-6') -ws = Precise('-1.123e-6') -xs = Precise('0.00000002') -ys = Precise('69696900000') -zs = Precise('0') +ws = FtPrecise('-1.123e-6') +ws = FtPrecise('-1.123e-6') +xs = FtPrecise('0.00000002') +ys = FtPrecise('69696900000') +zs = FtPrecise('0') -def test_precise(): +def test_FtPrecise(): assert ys * xs == '1393.938' assert xs * ys == '1393.938' @@ -45,31 +45,31 @@ def test_precise(): assert xs + zs == '0.00000002' assert ys + zs == '69696900000' - assert abs(Precise('-500.1')) == '500.1' - assert abs(Precise('213')) == '213' + assert abs(FtPrecise('-500.1')) == '500.1' + assert abs(FtPrecise('213')) == '213' - assert abs(Precise('-500.1')) == '500.1' - assert -Precise('213') == '-213' + assert abs(FtPrecise('-500.1')) == '500.1' + assert -FtPrecise('213') == '-213' - assert Precise('10.1') % Precise('0.5') == '0.1' - assert Precise('5550') % Precise('120') == '30' + assert FtPrecise('10.1') % FtPrecise('0.5') == '0.1' + assert FtPrecise('5550') % FtPrecise('120') == '30' - assert Precise('-0.0') == Precise('0') - assert Precise('5.534000') == Precise('5.5340') + assert FtPrecise('-0.0') == FtPrecise('0') + assert FtPrecise('5.534000') == FtPrecise('5.5340') - assert min(Precise('-3.1415'), Precise('-2')) == '-3.1415' + assert min(FtPrecise('-3.1415'), FtPrecise('-2')) == '-3.1415' - assert max(Precise('3.1415'), Precise('-2')) == '3.1415' + assert max(FtPrecise('3.1415'), FtPrecise('-2')) == '3.1415' - assert Precise('2') > Precise('1.2345') - assert not Precise('-3.1415') > Precise('-2') - assert not Precise('3.1415') > Precise('3.1415') - assert Precise.string_gt('3.14150000000000000000001', '3.1415') + assert FtPrecise('2') > FtPrecise('1.2345') + assert not FtPrecise('-3.1415') > FtPrecise('-2') + assert not FtPrecise('3.1415') > FtPrecise('3.1415') + assert FtPrecise.string_gt('3.14150000000000000000001', '3.1415') - assert Precise('3.1415') >= Precise('3.1415') - assert Precise('3.14150000000000000000001') >= Precise('3.1415') + assert FtPrecise('3.1415') >= FtPrecise('3.1415') + assert FtPrecise('3.14150000000000000000001') >= FtPrecise('3.1415') - assert not Precise('3.1415') < Precise('3.1415') + assert not FtPrecise('3.1415') < FtPrecise('3.1415') - assert Precise('3.1415') <= Precise('3.1415') - assert Precise('3.1415') <= Precise('3.14150000000000000000001') + assert FtPrecise('3.1415') <= FtPrecise('3.1415') + assert FtPrecise('3.1415') <= FtPrecise('3.14150000000000000000001') From ed004236ce8310a722b5737c5647ee4232a45068 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 10 Aug 2022 11:29:04 +0000 Subject: [PATCH 220/220] Add float initializer to FtPrecise --- freqtrade/exchange/exchange.py | 4 ++-- freqtrade/util/ft_precise.py | 7 +++++-- tests/exchange/test_ccxt_precise.py | 5 +++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 2806a4f42..18598e92d 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -709,8 +709,8 @@ class Exchange: # counting_mode=self.precisionMode, # )) if self.precisionMode == TICK_SIZE: - precision = FtPrecise(str(self.markets[pair]['precision']['price'])) - price_str = FtPrecise(str(price)) + precision = FtPrecise(self.markets[pair]['precision']['price']) + price_str = FtPrecise(price) missing = price_str % precision if not missing == FtPrecise("0"): price = round(float(str(price_str - missing + precision)), 14) diff --git a/freqtrade/util/ft_precise.py b/freqtrade/util/ft_precise.py index 9c79552c2..aba0517a9 100644 --- a/freqtrade/util/ft_precise.py +++ b/freqtrade/util/ft_precise.py @@ -1,9 +1,12 @@ """ Slim wrapper around ccxt's Precise (string math) -To have imports from freqtrade +To have imports from freqtrade - and support float initializers """ from ccxt import Precise class FtPrecise(Precise): - pass + def __init__(self, number, decimals=None): + if not isinstance(number, str): + number = str(number) + super().__init__(number, decimals) diff --git a/tests/exchange/test_ccxt_precise.py b/tests/exchange/test_ccxt_precise.py index 770dde13c..8b599093f 100644 --- a/tests/exchange/test_ccxt_precise.py +++ b/tests/exchange/test_ccxt_precise.py @@ -73,3 +73,8 @@ def test_FtPrecise(): assert FtPrecise('3.1415') <= FtPrecise('3.1415') assert FtPrecise('3.1415') <= FtPrecise('3.14150000000000000000001') + + assert FtPrecise(213) == '213' + assert FtPrecise(-213) == '-213' + assert str(FtPrecise(-213)) == '-213' + assert FtPrecise(213.2) == '213.2'