From 16a516a882f8936df3e4191e0311cedbc9d7a120 Mon Sep 17 00:00:00 2001 From: Italo Date: Wed, 19 Jan 2022 01:50:15 +0000 Subject: [PATCH 001/159] added plot functionality --- freqtrade/optimize/hyperopt.py | 65 +++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 209edd157..cfbc3ea82 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -32,6 +32,11 @@ from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss # noqa: F4 from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer from freqtrade.optimize.optimize_reports import generate_strategy_stats from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver +from skopt.plots import plot_convergence, plot_regret, plot_evaluations, plot_objective +import matplotlib.pyplot as plt +import numpy as np +import random +from sklearn.base import clone # Suppress scikit-learn FutureWarnings from skopt @@ -476,7 +481,12 @@ class Hyperopt: asked = self.opt.ask(n_points=current_jobs) f_val = self.run_optimizer_parallel(parallel, asked, i) - self.opt.tell(asked, [v['loss'] for v in f_val]) + res = self.opt.tell(asked, [v['loss'] for v in f_val]) + + self.plot_optimizer(res, path='user_data/scripts', convergence=False, regret=False, mse=True, objective=True, jobs=jobs) + + if res.models and hasattr(res.models[-1], "kernel_"): + print(f'kernel: {res.models[-1].kernel_}') # Calculate progressbar outputs for j, val in enumerate(f_val): @@ -521,3 +531,56 @@ class Hyperopt: # This is printed when Ctrl+C is pressed quickly, before first epochs have # a chance to be evaluated. print("No epochs evaluated yet, no best result.") + + def plot_mse(self, res, ax, jobs): + if len(res.x_iters) < 10: + return + + if not hasattr(self, 'mse_list'): + self.mse_list = [] + + model = clone(res.models[-1]) + i_subset = random.sample(range(len(res.x_iters)), 100) if len(res.x_iters) > 100 else range(len(res.x_iters)) + + i_train = random.sample(i_subset, round(.8*len(i_subset))) # get 80% random indices + x_train = [x for i, x in enumerate(res.x_iters) if i in i_train] + y_train = [y for i, y in enumerate(res.func_vals) if i in i_train] + + i_test = [i for i in i_subset if i not in i_train] # get 20% random indices + x_test = [x for i, x in enumerate(res.x_iters) if i in i_test] + y_test = [y for i, y in enumerate(res.func_vals) if i in i_test] + model.fit(np.array(x_train), np.array(y_train)) + y_pred, sigma = model.predict(np.array(x_test), return_std=True) + mse = np.mean((y_test - y_pred) ** 2) + self.mse_list.append(mse) + + ax.plot(range(INITIAL_POINTS, INITIAL_POINTS + jobs * len(self.mse_list), jobs), self.mse_list, label='MSE', marker=".", markersize=12, lw=2) + + def plot_optimizer(self, res, path, jobs, convergence=True, regret=True, evaluations=True, objective=True, mse=True): + path = Path(path) + if convergence: + ax = plot_convergence(res) + ax.flatten()[0].figure.savefig(path / 'convergence.png') + + if regret: + ax = plot_regret(res) + ax.flatten()[0].figure.savefig(path / 'regret.png') + + if evaluations: +# print('evaluations') + ax = plot_evaluations(res) + ax.flatten()[0].figure.savefig(path / 'evaluations.png') + + if objective and res.models: +# print('objective') + ax = plot_objective(res, sample_source='result', n_samples=50, n_points=10) + ax.flatten()[0].figure.savefig(path / 'objective.png') + + if mse and res.models: +# print('mse') + fig, ax = plt.subplots() + ax.set_ylabel('MSE') + ax.set_xlabel('Epoch') + ax.set_title('MSE') + ax = self.plot_mse(res, ax, jobs) + fig.savefig(path / 'mse.png') From 2eec51bfcbdc27279b21390cc5fa3ee7069233f3 Mon Sep 17 00:00:00 2001 From: Italo Date: Wed, 19 Jan 2022 02:00:14 +0000 Subject: [PATCH 002/159] Update requirements-hyperopt.txt --- requirements-hyperopt.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-hyperopt.txt b/requirements-hyperopt.txt index 122243bf2..57bb25e2c 100644 --- a/requirements-hyperopt.txt +++ b/requirements-hyperopt.txt @@ -8,3 +8,4 @@ scikit-optimize==0.9.0 filelock==3.4.2 joblib==1.1.0 progressbar2==4.0.0 +matplotlib \ No newline at end of file From 52206e6f41926ef89f7d9c051c377de9fc16f7ff Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Thu, 20 Jan 2022 17:15:05 +0000 Subject: [PATCH 003/159] add buy tag to plot --- freqtrade/plot/plotting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py index 3769d4c5a..b8a747105 100644 --- a/freqtrade/plot/plotting.py +++ b/freqtrade/plot/plotting.py @@ -236,6 +236,7 @@ def plot_trades(fig, trades: pd.DataFrame) -> make_subplots: if trades is not None and len(trades) > 0: # Create description for sell summarizing the trade trades['desc'] = trades.apply(lambda row: f"{row['profit_ratio']:.2%}, " + f"{row['buy_tag']}, " f"{row['sell_reason']}, " f"{row['trade_duration']} min", axis=1) From 0ce6c150ff6e1dfdba0a3a7bdda97288fd77eaa0 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sat, 22 Jan 2022 14:06:45 +0000 Subject: [PATCH 004/159] set stoploss at trade creation --- freqtrade/optimize/backtesting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index ae4001f5f..9cfeedd75 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -521,6 +521,7 @@ class Backtesting: exchange='backtesting', orders=[] ) + trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss, initial=True) order = Order( ft_is_open=False, From a2fb241a3b210f100db025815fb3542410476b45 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Mon, 24 Jan 2022 01:35:42 +0000 Subject: [PATCH 005/159] increase initial points to 64 --- freqtrade/optimize/hyperopt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index cfbc3ea82..f49f3f307 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -50,7 +50,7 @@ progressbar.streams.wrap_stdout() logger = logging.getLogger(__name__) -INITIAL_POINTS = 30 +INITIAL_POINTS = 64 # Keep no more than SKOPT_MODEL_QUEUE_SIZE models # in the skopt model queue, to optimize memory consumption From 992eac9efaf8c7bdc98abd0c350ccb8930555cd0 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sat, 5 Feb 2022 17:36:19 +0000 Subject: [PATCH 006/159] Update hyperopt.py --- freqtrade/optimize/hyperopt.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 60c54fe40..5e59135bd 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -50,7 +50,7 @@ progressbar.streams.wrap_stdout() logger = logging.getLogger(__name__) -INITIAL_POINTS = 64 +INITIAL_POINTS = 32 # Keep no more than SKOPT_MODEL_QUEUE_SIZE models # in the skopt model queue, to optimize memory consumption @@ -532,7 +532,8 @@ class Hyperopt: # a chance to be evaluated. print("No epochs evaluated yet, no best result.") - def plot_mse(self, res, ax, jobs): + def plot_mse(self, res, ax, jobs): + from sklearn.model_selection import cross_val_score if len(res.x_iters) < 10: return @@ -540,19 +541,26 @@ class Hyperopt: self.mse_list = [] model = clone(res.models[-1]) - i_subset = random.sample(range(len(res.x_iters)), 100) if len(res.x_iters) > 100 else range(len(res.x_iters)) + # i_subset = random.sample(range(len(res.x_iters)), 100) if len(res.x_iters) > 100 else range(len(res.x_iters)) - i_train = random.sample(i_subset, round(.8*len(i_subset))) # get 80% random indices - x_train = [x for i, x in enumerate(res.x_iters) if i in i_train] - y_train = [y for i, y in enumerate(res.func_vals) if i in i_train] + # i_train = random.sample(i_subset, round(.8*len(i_subset))) # get 80% random indices + # x_train = [x for i, x in enumerate(res.x_iters) if i in i_train] + # y_train = [y for i, y in enumerate(res.func_vals) if i in i_train] - i_test = [i for i in i_subset if i not in i_train] # get 20% random indices - x_test = [x for i, x in enumerate(res.x_iters) if i in i_test] - y_test = [y for i, y in enumerate(res.func_vals) if i in i_test] - model.fit(np.array(x_train), np.array(y_train)) - y_pred, sigma = model.predict(np.array(x_test), return_std=True) - mse = np.mean((y_test - y_pred) ** 2) - self.mse_list.append(mse) + # i_test = [i for i in i_subset if i not in i_train] # get 20% random indices + # x_test = [x for i, x in enumerate(res.x_iters) if i in i_test] + # y_test = [y for i, y in enumerate(res.func_vals) if i in i_test] + model.fit(res.x_iters, res.func_vals) + # Perform a cross-validation estimate of the coefficient of determination using + # the cross_validation module using all CPUs available on the machine + # K = 5 # folds + R2 = cross_val_score(model, X=res.x_iters, y=res.func_vals, cv=5, n_jobs=jobs).mean() + print(f'R2: {R2}') + R2 = R2 if R2 > -5 else -5 + self.mse_list.append(R2) + # y_pred, sigma = model.predict(np.array(x_test), return_std=True) + # mse = np.mean((y_test - y_pred) ** 2) + # self.mse_list.append(mse) ax.plot(range(INITIAL_POINTS, INITIAL_POINTS + jobs * len(self.mse_list), jobs), self.mse_list, label='MSE', marker=".", markersize=12, lw=2) From 6a4cae1f8c2f7569dff9156431e36dd1162810b9 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 6 Feb 2022 00:17:48 +0000 Subject: [PATCH 007/159] Update hyperopt.py --- freqtrade/optimize/hyperopt.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 5e59135bd..25055d06c 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -540,7 +540,7 @@ class Hyperopt: if not hasattr(self, 'mse_list'): self.mse_list = [] - model = clone(res.models[-1]) + # model = clone(res.models[-1]) # i_subset = random.sample(range(len(res.x_iters)), 100) if len(res.x_iters) > 100 else range(len(res.x_iters)) # i_train = random.sample(i_subset, round(.8*len(i_subset))) # get 80% random indices @@ -550,11 +550,11 @@ class Hyperopt: # i_test = [i for i in i_subset if i not in i_train] # get 20% random indices # x_test = [x for i, x in enumerate(res.x_iters) if i in i_test] # y_test = [y for i, y in enumerate(res.func_vals) if i in i_test] - model.fit(res.x_iters, res.func_vals) + # model.fit(res.x_iters, res.func_vals) # Perform a cross-validation estimate of the coefficient of determination using # the cross_validation module using all CPUs available on the machine # K = 5 # folds - R2 = cross_val_score(model, X=res.x_iters, y=res.func_vals, cv=5, n_jobs=jobs).mean() + R2 = cross_val_score(res.models[-1], X=res.x_iters, y=res.func_vals, cv=5, n_jobs=jobs).mean() print(f'R2: {R2}') R2 = R2 if R2 > -5 else -5 self.mse_list.append(R2) From 6c1729e20b6ea87d341ad8b2e204409c7ded5be6 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 6 Feb 2022 01:07:30 +0000 Subject: [PATCH 008/159] ignore warnings --- freqtrade/optimize/hyperopt.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 25055d06c..d99c2b3b0 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -554,7 +554,9 @@ class Hyperopt: # Perform a cross-validation estimate of the coefficient of determination using # the cross_validation module using all CPUs available on the machine # K = 5 # folds - R2 = cross_val_score(res.models[-1], X=res.x_iters, y=res.func_vals, cv=5, n_jobs=jobs).mean() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + R2 = cross_val_score(res.models[-1], X=res.x_iters, y=res.func_vals, cv=5, n_jobs=jobs).mean() print(f'R2: {R2}') R2 = R2 if R2 > -5 else -5 self.mse_list.append(R2) From adf8f6b2d503649effaed161e81108df10483a76 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 6 Feb 2022 10:33:49 +0000 Subject: [PATCH 009/159] Update hyperopt.py --- freqtrade/optimize/hyperopt.py | 56 +++++++++++----------------------- 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index d99c2b3b0..19132a14a 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -32,18 +32,17 @@ from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss # noqa: F4 from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer from freqtrade.optimize.optimize_reports import generate_strategy_stats from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver -from skopt.plots import plot_convergence, plot_regret, plot_evaluations, plot_objective import matplotlib.pyplot as plt import numpy as np import random -from sklearn.base import clone - # Suppress scikit-learn FutureWarnings from skopt with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=FutureWarning) from skopt import Optimizer from skopt.space import Dimension + from sklearn.model_selection import cross_val_score + from skopt.plots import plot_convergence, plot_regret, plot_evaluations, plot_objective progressbar.streams.wrap_stderr() progressbar.streams.wrap_stdout() @@ -483,7 +482,7 @@ class Hyperopt: f_val = self.run_optimizer_parallel(parallel, asked, i) res = self.opt.tell(asked, [v['loss'] for v in f_val]) - self.plot_optimizer(res, path='user_data/scripts', convergence=False, regret=False, mse=True, objective=True, jobs=jobs) + self.plot_optimizer(res, path='user_data/scripts', convergence=False, regret=False, r2=True, objective=True, jobs=jobs) if res.models and hasattr(res.models[-1], "kernel_"): print(f'kernel: {res.models[-1].kernel_}') @@ -532,41 +531,21 @@ class Hyperopt: # a chance to be evaluated. print("No epochs evaluated yet, no best result.") - def plot_mse(self, res, ax, jobs): - from sklearn.model_selection import cross_val_score + def plot_r2(self, res, ax, jobs): if len(res.x_iters) < 10: return - if not hasattr(self, 'mse_list'): - self.mse_list = [] + if not hasattr(self, 'r2_list'): + self.r2_list = [] - # model = clone(res.models[-1]) - # i_subset = random.sample(range(len(res.x_iters)), 100) if len(res.x_iters) > 100 else range(len(res.x_iters)) - - # i_train = random.sample(i_subset, round(.8*len(i_subset))) # get 80% random indices - # x_train = [x for i, x in enumerate(res.x_iters) if i in i_train] - # y_train = [y for i, y in enumerate(res.func_vals) if i in i_train] - - # i_test = [i for i in i_subset if i not in i_train] # get 20% random indices - # x_test = [x for i, x in enumerate(res.x_iters) if i in i_test] - # y_test = [y for i, y in enumerate(res.func_vals) if i in i_test] - # model.fit(res.x_iters, res.func_vals) - # Perform a cross-validation estimate of the coefficient of determination using - # the cross_validation module using all CPUs available on the machine - # K = 5 # folds - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - R2 = cross_val_score(res.models[-1], X=res.x_iters, y=res.func_vals, cv=5, n_jobs=jobs).mean() - print(f'R2: {R2}') - R2 = R2 if R2 > -5 else -5 - self.mse_list.append(R2) - # y_pred, sigma = model.predict(np.array(x_test), return_std=True) - # mse = np.mean((y_test - y_pred) ** 2) - # self.mse_list.append(mse) + r2 = cross_val_score(res.models[-1], X=res.x_iters, y=res.func_vals, scoring='r2', cv=5, n_jobs=jobs).mean() + print(f'R2: {r2}') + r2 = r2 if r2 > -5 else -5 + self.r2_list.append(r2) - ax.plot(range(INITIAL_POINTS, INITIAL_POINTS + jobs * len(self.mse_list), jobs), self.mse_list, label='MSE', marker=".", markersize=12, lw=2) + ax.plot(range(INITIAL_POINTS, INITIAL_POINTS + jobs * len(self.r2_list), jobs), self.r2_list, label='R2', marker=".", markersize=12, lw=2) - def plot_optimizer(self, res, path, jobs, convergence=True, regret=True, evaluations=True, objective=True, mse=True): + def plot_optimizer(self, res, path, jobs, convergence=True, regret=True, evaluations=True, objective=True, r2=True): path = Path(path) if convergence: ax = plot_convergence(res) @@ -586,11 +565,10 @@ class Hyperopt: ax = plot_objective(res, sample_source='result', n_samples=50, n_points=10) ax.flatten()[0].figure.savefig(path / 'objective.png') - if mse and res.models: -# print('mse') + if r2 and res.models: fig, ax = plt.subplots() - ax.set_ylabel('MSE') + ax.set_ylabel('R2') ax.set_xlabel('Epoch') - ax.set_title('MSE') - ax = self.plot_mse(res, ax, jobs) - fig.savefig(path / 'mse.png') + ax.set_title('R2') + ax = self.plot_r2(res, ax, jobs) + fig.savefig(path / 'r2.png') From d03378b1df7c76b7d1931c174af9197abf977357 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 6 Feb 2022 15:32:59 +0000 Subject: [PATCH 010/159] Update hyperopt.py --- freqtrade/optimize/hyperopt.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 19132a14a..ba32943cb 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -538,7 +538,10 @@ class Hyperopt: if not hasattr(self, 'r2_list'): self.r2_list = [] - r2 = cross_val_score(res.models[-1], X=res.x_iters, y=res.func_vals, scoring='r2', cv=5, n_jobs=jobs).mean() + model = res.models[-1] + model.criterion = 'squared_error' + + r2 = cross_val_score(model, X=res.x_iters, y=res.func_vals, scoring='r2', cv=5, n_jobs=jobs).mean() print(f'R2: {r2}') r2 = r2 if r2 > -5 else -5 self.r2_list.append(r2) From d2a54483050a587facad827afa6d3177cd68d702 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Fri, 11 Mar 2022 17:38:32 +0000 Subject: [PATCH 011/159] Update hyperopt.py --- freqtrade/optimize/hyperopt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index ba32943cb..aa255967e 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -486,6 +486,7 @@ class Hyperopt: if res.models and hasattr(res.models[-1], "kernel_"): print(f'kernel: {res.models[-1].kernel_}') + print(datetime.now()) # Calculate progressbar outputs for j, val in enumerate(f_val): @@ -542,7 +543,6 @@ class Hyperopt: model.criterion = 'squared_error' r2 = cross_val_score(model, X=res.x_iters, y=res.func_vals, scoring='r2', cv=5, n_jobs=jobs).mean() - print(f'R2: {r2}') r2 = r2 if r2 > -5 else -5 self.r2_list.append(r2) From 162e94455b3cf928ac68bd895a7674f1dbe0ce8b Mon Sep 17 00:00:00 2001 From: froggleston Date: Wed, 16 Mar 2022 12:16:24 +0000 Subject: [PATCH 012/159] Add support for storing buy candle indicator rows in backtesting results --- freqtrade/optimize/backtesting.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 79c861ee8..1a8c0903c 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -64,7 +64,8 @@ class Backtesting: config['dry_run'] = True self.strategylist: List[IStrategy] = [] self.all_results: Dict[str, Dict] = {} - + self.processed_dfs: Dict[str, Dict] = {} + self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config) self.dataprovider = DataProvider(self.config, None) @@ -136,6 +137,10 @@ class Backtesting: self.config['startup_candle_count'] = self.required_startup self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe) + self.enable_backtest_signal_candle_export = False + if self.config.get('enable_backtest_signal_candle_export', None) is not None: + self.enable_backtest_signal_candle_export = bool(self.config.get('enable_backtest_signal_candle_export')) + self.progress = BTProgress() self.abort = False @@ -636,6 +641,25 @@ class Backtesting: }) self.all_results[self.strategy.get_strategy_name()] = results + if self.enable_backtest_signal_candle_export: + signal_candles_only = {} + for pair in preprocessed_tmp.keys(): + signal_candles_only_df = DataFrame() + + pairdf = preprocessed_tmp[pair] + resdf = results['results'] + pairresults = resdf.loc[(resdf["pair"] == pair)] + + if pairdf.shape[0] > 0: + for t, v in pairresults.open_date.items(): + allinds = pairdf.loc[(pairdf['date'] < v)] + signal_inds = allinds.iloc[[-1]] + signal_candles_only_df = signal_candles_only_df.append(signal_inds) + + signal_candles_only[pair] = signal_candles_only_df + + self.processed_dfs[self.strategy.get_strategy_name()] = signal_candles_only + return min_date, max_date def start(self) -> None: From d796ce09352042160023235a404899d2973a55c7 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 20 Mar 2022 15:41:14 +0000 Subject: [PATCH 013/159] Update hyperopt.py 1. Try to get points using `self.opt.ask` first 2. Discard the points that have already been evaluated 3. Retry using `self.opt.ask` up to 3 times 4. If still some points are missing in respect to `n_points`, random sample some points 5. Repeat until at least `n_points` points in the `asked_non_tried` list 6. Return a list with legth truncated at `n_points` --- freqtrade/optimize/hyperopt.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index aa255967e..badaf2b3c 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -413,6 +413,31 @@ class Hyperopt: f'({(self.max_date - self.min_date).days} days)..') # Store non-trimmed data - will be trimmed after signal generation. dump(preprocessed, self.data_pickle_file) + + def get_asked_points(self, n_points: int) -> List[Any]: + ''' + Steps: + 1. Try to get points using `self.opt.ask` first + 2. Discard the points that have already been evaluated + 3. Retry using `self.opt.ask` up to 3 times + 4. If still some points are missing in respect to `n_points`, random sample some points + 5. Repeat until at least `n_points` points in the `asked_non_tried` list + 6. Return a list with legth truncated at `n_points` + ''' + i = 0 + asked_non_tried = [] + while i < 100: + if len(asked_non_tried) < n_points: + if i < 3: + asked = self.opt.ask(n_points=n_points) + else: + # use random sample if `self.opt.ask` returns points points already tried + asked = self.opt.space.rvs(n_samples=n_points * 5) + asked_non_tried += [x for x in asked if x not in self.opt.Xi and x not in asked_non_tried] + i += 1 + else: + break + return asked_non_tried[:n_points] def start(self) -> None: self.random_state = self._set_random_state(self.config.get('hyperopt_random_state', None)) @@ -478,11 +503,11 @@ class Hyperopt: n_rest = (i + 1) * jobs - self.total_epochs current_jobs = jobs - n_rest if n_rest > 0 else jobs - asked = self.opt.ask(n_points=current_jobs) + asked = self.get_asked_points(n_points=current_jobs) f_val = self.run_optimizer_parallel(parallel, asked, i) res = self.opt.tell(asked, [v['loss'] for v in f_val]) - self.plot_optimizer(res, path='user_data/scripts', convergence=False, regret=False, r2=True, objective=True, jobs=jobs) + self.plot_optimizer(res, path='user_data/scripts', convergence=False, regret=False, r2=False, objective=True, jobs=jobs) if res.models and hasattr(res.models[-1], "kernel_"): print(f'kernel: {res.models[-1].kernel_}') From e16bb1b34e381b9bb82b47d9e406f093479c5ffa Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 20 Mar 2022 16:02:03 +0000 Subject: [PATCH 014/159] Optimize only new points Enforce points returned from `self.opt.ask` have not been already evaluated --- freqtrade/optimize/hyperopt.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 9664e6f07..8b6225fa7 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -410,6 +410,35 @@ class Hyperopt: # Store non-trimmed data - will be trimmed after signal generation. dump(preprocessed, self.data_pickle_file) + def get_asked_points(self, n_points: int) -> List[List[Any]]: + ''' + Enforce points returned from `self.opt.ask` have not been already evaluated + + Steps: + 1. Try to get points using `self.opt.ask` first + 2. Discard the points that have already been evaluated + 3. Retry using `self.opt.ask` up to 3 times + 4. If still some points are missing in respect to `n_points`, random sample some points + 5. Repeat until at least `n_points` points in the `asked_non_tried` list + 6. Return a list with legth truncated at `n_points` + ''' + i = 0 + asked_non_tried: List[List[Any]] = [] + while i < 100: + if len(asked_non_tried) < n_points: + if i < 3: + asked = self.opt.ask(n_points=n_points) + else: + # use random sample if `self.opt.ask` returns points points already tried + asked = self.opt.space.rvs(n_samples=n_points * 5) + asked_non_tried += [x for x in asked + if x not in self.opt.Xi + and x not in asked_non_tried] + i += 1 + else: + break + return asked_non_tried[:n_points] + def start(self) -> None: self.random_state = self._set_random_state(self.config.get('hyperopt_random_state', None)) logger.info(f"Using optimizer random state: {self.random_state}") @@ -474,7 +503,7 @@ class Hyperopt: n_rest = (i + 1) * jobs - self.total_epochs current_jobs = jobs - n_rest if n_rest > 0 else jobs - asked = self.opt.ask(n_points=current_jobs) + asked = self.get_asked_points(n_points=current_jobs) f_val = self.run_optimizer_parallel(parallel, asked, i) self.opt.tell(asked, [v['loss'] for v in f_val]) From 0fd269e4f00feefe431a16f2fd45f4fd113dc5e7 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 20 Mar 2022 16:03:07 +0000 Subject: [PATCH 015/159] typo --- freqtrade/optimize/hyperopt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 8b6225fa7..55ae44b91 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -420,7 +420,7 @@ class Hyperopt: 3. Retry using `self.opt.ask` up to 3 times 4. If still some points are missing in respect to `n_points`, random sample some points 5. Repeat until at least `n_points` points in the `asked_non_tried` list - 6. Return a list with legth truncated at `n_points` + 6. Return a list with length truncated at `n_points` ''' i = 0 asked_non_tried: List[List[Any]] = [] From 23f1a1904bfa90d2fa00865e71023f869479adfe Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 20 Mar 2022 16:06:41 +0000 Subject: [PATCH 016/159] more compact --- freqtrade/optimize/hyperopt.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 55ae44b91..61e8913df 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -424,19 +424,15 @@ class Hyperopt: ''' i = 0 asked_non_tried: List[List[Any]] = [] - while i < 100: - if len(asked_non_tried) < n_points: - if i < 3: - asked = self.opt.ask(n_points=n_points) - else: - # use random sample if `self.opt.ask` returns points points already tried - asked = self.opt.space.rvs(n_samples=n_points * 5) - asked_non_tried += [x for x in asked - if x not in self.opt.Xi - and x not in asked_non_tried] - i += 1 + while i < 100 and len(asked_non_tried) < n_points: + if i < 3: + asked = self.opt.ask(n_points=n_points) else: - break + asked = self.opt.space.rvs(n_samples=n_points * 5) + asked_non_tried += [x for x in asked + if x not in self.opt.Xi + and x not in asked_non_tried] + i += 1 return asked_non_tried[:n_points] def start(self) -> None: From f8a674f24de013853e4b5acee075fc23b23bd64b Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 20 Mar 2022 16:08:38 +0000 Subject: [PATCH 017/159] make robust in case all points have been tried --- freqtrade/optimize/hyperopt.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 61e8913df..c1adbf45e 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -433,7 +433,10 @@ class Hyperopt: if x not in self.opt.Xi and x not in asked_non_tried] i += 1 - return asked_non_tried[:n_points] + if asked_non_tried: + return asked_non_tried[:n_points] + else: + return self.opt.ask(n_points=n_points) def start(self) -> None: self.random_state = self._set_random_state(self.config.get('hyperopt_random_state', None)) From fca93d8dfec22dad88496774c8482d07d25ca325 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Sun, 20 Mar 2022 16:12:06 +0000 Subject: [PATCH 018/159] Update hyperopt.py --- freqtrade/optimize/hyperopt.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index badaf2b3c..bbdc8bf27 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -414,30 +414,33 @@ class Hyperopt: # Store non-trimmed data - will be trimmed after signal generation. dump(preprocessed, self.data_pickle_file) - def get_asked_points(self, n_points: int) -> List[Any]: + def get_asked_points(self, n_points: int) -> List[List[Any]]: ''' + Enforce points returned from `self.opt.ask` have not been already evaluated + Steps: 1. Try to get points using `self.opt.ask` first 2. Discard the points that have already been evaluated 3. Retry using `self.opt.ask` up to 3 times 4. If still some points are missing in respect to `n_points`, random sample some points 5. Repeat until at least `n_points` points in the `asked_non_tried` list - 6. Return a list with legth truncated at `n_points` + 6. Return a list with length truncated at `n_points` ''' i = 0 - asked_non_tried = [] - while i < 100: - if len(asked_non_tried) < n_points: - if i < 3: - asked = self.opt.ask(n_points=n_points) - else: - # use random sample if `self.opt.ask` returns points points already tried - asked = self.opt.space.rvs(n_samples=n_points * 5) - asked_non_tried += [x for x in asked if x not in self.opt.Xi and x not in asked_non_tried] - i += 1 + asked_non_tried: List[List[Any]] = [] + while i < 100 and len(asked_non_tried) < n_points: + if i < 3: + asked = self.opt.ask(n_points=n_points) else: - break - return asked_non_tried[:n_points] + asked = self.opt.space.rvs(n_samples=n_points * 5) + asked_non_tried += [x for x in asked + if x not in self.opt.Xi + and x not in asked_non_tried] + i += 1 + if asked_non_tried: + return asked_non_tried[:n_points] + else: + return self.opt.ask(n_points=n_points) def start(self) -> None: self.random_state = self._set_random_state(self.config.get('hyperopt_random_state', None)) From 37a43019d6427952bfabd17b838590155fde14f1 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:36:53 +0000 Subject: [PATCH 019/159] fix - clear cache before calling `ask` - avoid errors in case asked_non_tried has less than n_points elements --- freqtrade/optimize/hyperopt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index c1adbf45e..fe587a702 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -426,6 +426,7 @@ class Hyperopt: asked_non_tried: List[List[Any]] = [] while i < 100 and len(asked_non_tried) < n_points: if i < 3: + self.opt.cache_ = {} asked = self.opt.ask(n_points=n_points) else: asked = self.opt.space.rvs(n_samples=n_points * 5) @@ -434,7 +435,7 @@ class Hyperopt: and x not in asked_non_tried] i += 1 if asked_non_tried: - return asked_non_tried[:n_points] + return asked_non_tried[:min(len(asked_non_tried), n_points)] else: return self.opt.ask(n_points=n_points) From 2733aa33b6661523f721bd039cb8fd9e2ccdc7f1 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Tue, 22 Mar 2022 00:28:11 +0000 Subject: [PATCH 020/159] Update hyperopt.py --- freqtrade/optimize/hyperopt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index bbdc8bf27..f08fa7233 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -430,6 +430,7 @@ class Hyperopt: asked_non_tried: List[List[Any]] = [] while i < 100 and len(asked_non_tried) < n_points: if i < 3: + self.opt.cache_ = {} asked = self.opt.ask(n_points=n_points) else: asked = self.opt.space.rvs(n_samples=n_points * 5) @@ -438,7 +439,7 @@ class Hyperopt: and x not in asked_non_tried] i += 1 if asked_non_tried: - return asked_non_tried[:n_points] + return asked_non_tried[:min(len(asked_non_tried), n_points)] else: return self.opt.ask(n_points=n_points) From b5a346a46de13e7aefcd6be27ac354e701322b6d Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Tue, 22 Mar 2022 11:01:38 +0000 Subject: [PATCH 021/159] Update hyperopt.py --- freqtrade/optimize/hyperopt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index f08fa7233..d3f6a72f2 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -431,7 +431,7 @@ class Hyperopt: while i < 100 and len(asked_non_tried) < n_points: if i < 3: self.opt.cache_ = {} - asked = self.opt.ask(n_points=n_points) + asked = self.opt.ask(n_points=n_points * 5) else: asked = self.opt.space.rvs(n_samples=n_points * 5) asked_non_tried += [x for x in asked From 229b0b037eb3440f9fc93bd5d809f05eb5506ff4 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:33:35 +0100 Subject: [PATCH 022/159] reduce search loops --- freqtrade/optimize/hyperopt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index fe587a702..4fad76570 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -424,10 +424,10 @@ class Hyperopt: ''' i = 0 asked_non_tried: List[List[Any]] = [] - while i < 100 and len(asked_non_tried) < n_points: + while i < 5 and len(asked_non_tried) < n_points: if i < 3: self.opt.cache_ = {} - asked = self.opt.ask(n_points=n_points) + asked = self.opt.ask(n_points=n_points * 5) else: asked = self.opt.space.rvs(n_samples=n_points * 5) asked_non_tried += [x for x in asked From a3b401a762bbdda75191956ea251d097c08e7a32 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:29:14 +0100 Subject: [PATCH 023/159] highlight random points in hyperopt results table --- freqtrade/optimize/hyperopt.py | 21 ++++++++++++++++----- freqtrade/optimize/hyperopt_tools.py | 12 +++++++----- tests/conftest.py | 13 ++++++++++++- tests/optimize/test_hyperopt.py | 2 ++ 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 4fad76570..35f382469 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -10,7 +10,7 @@ import warnings from datetime import datetime, timezone from math import ceil from pathlib import Path -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Tuple import progressbar import rapidjson @@ -410,7 +410,7 @@ class Hyperopt: # Store non-trimmed data - will be trimmed after signal generation. dump(preprocessed, self.data_pickle_file) - def get_asked_points(self, n_points: int) -> List[List[Any]]: + def get_asked_points(self, n_points: int) -> Tuple[List[List[Any]], List[bool]]: ''' Enforce points returned from `self.opt.ask` have not been already evaluated @@ -424,20 +424,30 @@ class Hyperopt: ''' i = 0 asked_non_tried: List[List[Any]] = [] + is_random: List[bool] = [] while i < 5 and len(asked_non_tried) < n_points: if i < 3: self.opt.cache_ = {} asked = self.opt.ask(n_points=n_points * 5) + is_random = [False for _ in range(len(asked))] else: asked = self.opt.space.rvs(n_samples=n_points * 5) + is_random = [True for _ in range(len(asked))] asked_non_tried += [x for x in asked if x not in self.opt.Xi and x not in asked_non_tried] + is_random += [rand for x, rand in zip(asked, is_random) + if x not in self.opt.Xi + and x not in asked_non_tried] i += 1 + if asked_non_tried: - return asked_non_tried[:min(len(asked_non_tried), n_points)] + return ( + asked_non_tried[:min(len(asked_non_tried), n_points)], + is_random[:min(len(asked_non_tried), n_points)] + ) else: - return self.opt.ask(n_points=n_points) + 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)) @@ -503,7 +513,7 @@ class Hyperopt: n_rest = (i + 1) * jobs - self.total_epochs current_jobs = jobs - n_rest if n_rest > 0 else jobs - asked = self.get_asked_points(n_points=current_jobs) + asked, is_random = self.get_asked_points(n_points=current_jobs) f_val = self.run_optimizer_parallel(parallel, asked, i) self.opt.tell(asked, [v['loss'] for v in f_val]) @@ -522,6 +532,7 @@ class Hyperopt: # evaluations can take different time. Here they are aligned in the # order they will be shown to the user. val['is_best'] = is_best + val['is_random'] = is_random[j] self.print_results(val) if is_best: diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index 8c84f772a..83df7e83c 100755 --- a/freqtrade/optimize/hyperopt_tools.py +++ b/freqtrade/optimize/hyperopt_tools.py @@ -322,12 +322,12 @@ class HyperoptTools(): 'results_metrics.profit_total', 'results_metrics.holding_avg', 'results_metrics.max_drawdown', 'results_metrics.max_drawdown_account', 'results_metrics.max_drawdown_abs', - 'loss', 'is_initial_point', 'is_best']] + 'loss', 'is_initial_point', 'is_random', 'is_best']] trials.columns = [ 'Best', 'Epoch', 'Trades', ' Win Draw Loss', 'Avg profit', 'Total profit', 'Profit', 'Avg duration', 'max_drawdown', 'max_drawdown_account', - 'max_drawdown_abs', 'Objective', 'is_initial_point', 'is_best' + 'max_drawdown_abs', 'Objective', 'is_initial_point', 'is_random', 'is_best' ] return trials @@ -349,9 +349,11 @@ class HyperoptTools(): trials = HyperoptTools.prepare_trials_columns(trials, has_account_drawdown) trials['is_profit'] = False - trials.loc[trials['is_initial_point'], 'Best'] = '* ' + trials.loc[trials['is_initial_point'] | trials['is_random'], 'Best'] = '* ' trials.loc[trials['is_best'], 'Best'] = 'Best' - trials.loc[trials['is_initial_point'] & trials['is_best'], 'Best'] = '* Best' + trials.loc[ + (trials['is_initial_point'] | trials['is_random']) & trials['is_best'], + 'Best'] = '* Best' trials.loc[trials['Total profit'] > 0, 'is_profit'] = True trials['Trades'] = trials['Trades'].astype(str) # perc_multi = 1 if legacy_mode else 100 @@ -407,7 +409,7 @@ class HyperoptTools(): trials.iat[i, j] = "{}{}{}".format(Style.BRIGHT, str(trials.loc[i][j]), Style.RESET_ALL) - trials = trials.drop(columns=['is_initial_point', 'is_best', 'is_profit']) + trials = trials.drop(columns=['is_initial_point', 'is_best', 'is_profit', 'is_random']) if remove_header > 0: table = tabulate.tabulate( trials.to_dict(orient='list'), tablefmt='orgtbl', diff --git a/tests/conftest.py b/tests/conftest.py index 57122c01c..1dd6e8869 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2053,6 +2053,7 @@ def saved_hyperopt_results(): 'total_profit': -0.00125625, 'current_epoch': 1, 'is_initial_point': True, + 'is_random': False, 'is_best': True, }, { @@ -2069,6 +2070,7 @@ def saved_hyperopt_results(): 'total_profit': 6.185e-05, 'current_epoch': 2, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': 14.241196856510731, @@ -2079,6 +2081,7 @@ def saved_hyperopt_results(): 'total_profit': -0.13639474, 'current_epoch': 3, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': 100000, @@ -2086,7 +2089,7 @@ def saved_hyperopt_results(): 'params_details': {'buy': {'mfi-value': 13, 'fastd-value': 35, 'adx-value': 39, 'rsi-value': 29, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': True, 'trigger': 'macd_cross_signal'}, 'sell': {'sell-mfi-value': 87, 'sell-fastd-value': 54, 'sell-adx-value': 63, 'sell-rsi-value': 93, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper'}, 'roi': {0: 0.411946348378729, 215: 0.2052334363683207, 891: 0.06264755784937427, 2293: 0}, 'stoploss': {'stoploss': -0.11818343570194478}}, # noqa: E501 'results_metrics': {'total_trades': 0, 'wins': 0, 'draws': 0, 'losses': 0, 'profit_mean': None, 'profit_median': None, 'profit_total': 0, 'profit': 0.0, 'holding_avg': timedelta()}, # noqa: E501 'results_explanation': ' 0 trades. Avg profit nan%. Total profit 0.00000000 BTC ( 0.00Σ%). Avg duration nan min.', # noqa: E501 - 'total_profit': 0, 'current_epoch': 4, 'is_initial_point': True, 'is_best': False + 'total_profit': 0, 'current_epoch': 4, 'is_initial_point': True, 'is_random': False, 'is_best': False }, { 'loss': 0.22195522184191518, 'params_dict': {'mfi-value': 17, 'fastd-value': 21, 'adx-value': 38, 'rsi-value': 33, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': True, 'rsi-enabled': False, 'trigger': 'macd_cross_signal', 'sell-mfi-value': 87, 'sell-fastd-value': 82, 'sell-adx-value': 78, 'sell-rsi-value': 69, 'sell-mfi-enabled': True, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': False, 'sell-trigger': 'sell-macd_cross_signal', 'roi_t1': 1269, 'roi_t2': 601, 'roi_t3': 444, 'roi_p1': 0.07280999507931168, 'roi_p2': 0.08946698095898986, 'roi_p3': 0.1454876733325284, 'stoploss': -0.18181041180901014}, # noqa: E501 @@ -2096,6 +2099,7 @@ def saved_hyperopt_results(): 'total_profit': -0.002480140000000001, 'current_epoch': 5, 'is_initial_point': True, + 'is_random': False, 'is_best': True }, { 'loss': 0.545315889154162, @@ -2106,6 +2110,7 @@ def saved_hyperopt_results(): 'total_profit': -0.0041773, 'current_epoch': 6, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': 4.713497421432944, @@ -2118,6 +2123,7 @@ def saved_hyperopt_results(): 'total_profit': -0.06339929, 'current_epoch': 7, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': 20.0, # noqa: E501 @@ -2128,6 +2134,7 @@ def saved_hyperopt_results(): 'total_profit': 0.0, 'current_epoch': 8, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': 2.4731817780991223, @@ -2138,6 +2145,7 @@ def saved_hyperopt_results(): 'total_profit': -0.044050070000000004, # noqa: E501 'current_epoch': 9, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': -0.2604606005845212, # noqa: E501 @@ -2148,6 +2156,7 @@ def saved_hyperopt_results(): 'total_profit': 0.00021629, 'current_epoch': 10, 'is_initial_point': True, + 'is_random': False, 'is_best': True }, { 'loss': 4.876465945994304, # noqa: E501 @@ -2159,6 +2168,7 @@ def saved_hyperopt_results(): 'total_profit': -0.07436117, 'current_epoch': 11, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': 100000, @@ -2169,6 +2179,7 @@ def saved_hyperopt_results(): 'total_profit': 0, 'current_epoch': 12, 'is_initial_point': True, + 'is_random': False, 'is_best': False } ] diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index cc551277a..ef32e2466 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -41,6 +41,7 @@ def generate_result_metrics(): 'max_drawdown_abs': 0.001, 'loss': 0.001, 'is_initial_point': 0.001, + 'is_random': False, 'is_best': 1, } @@ -247,6 +248,7 @@ def test_log_results_if_loss_improves(hyperopt, capsys) -> None: 'total_profit': 0, 'current_epoch': 2, # This starts from 1 (in a human-friendly manner) 'is_initial_point': False, + 'is_random': False, 'is_best': True } ) From 9f171193ef2b893b7f7c9269b9a2c6b796f0d71c Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Wed, 30 Mar 2022 09:39:07 +0100 Subject: [PATCH 024/159] Revert "Merge branch 'plot_hyperopt_stats' into opt-ask-force-new-points" This reverts commit 4eb9cc6e8b7bc99b543c4acbfa6c2b07f67d54e5, reversing changes made to a3b401a762bbdda75191956ea251d097c08e7a32. --- .github/workflows/ci.yml | 10 +-- .github/workflows/docker_update_readme.yml | 2 +- docs/includes/pricing.md | 8 +- docs/requirements-docs.txt | 7 +- docs/strategy-advanced.md | 17 ++-- freqtrade/__init__.py | 17 +++- freqtrade/optimize/hyperopt.py | 89 +------------------ freqtrade/resolvers/iresolver.py | 60 ++++--------- requirements-dev.txt | 12 +-- requirements-hyperopt.txt | 1 - requirements.txt | 8 +- tests/conftest.py | 30 +++---- tests/exchange/test_exchange.py | 2 +- .../strategy/strats/hyperoptable_strategy.py | 88 +++++++++++++++++- tests/strategy/strats/strategy_test_v2.py | 2 +- 15 files changed, 169 insertions(+), 184 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8df7ab10..216a53bc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,14 +31,14 @@ jobs: python-version: ${{ matrix.python-version }} - name: Cache_dependencies - uses: actions/cache@v3 + uses: actions/cache@v2 id: cache with: path: ~/dependencies/ key: ${{ runner.os }}-dependencies - name: pip cache (linux) - uses: actions/cache@v3 + uses: actions/cache@v2 if: runner.os == 'Linux' with: path: ~/.cache/pip @@ -126,14 +126,14 @@ jobs: python-version: ${{ matrix.python-version }} - name: Cache_dependencies - uses: actions/cache@v3 + uses: actions/cache@v2 id: cache with: path: ~/dependencies/ key: ${{ runner.os }}-dependencies - name: pip cache (macOS) - uses: actions/cache@v3 + uses: actions/cache@v2 if: runner.os == 'macOS' with: path: ~/Library/Caches/pip @@ -218,7 +218,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Pip cache (Windows) - uses: actions/cache@v3 + uses: actions/cache@preview with: path: ~\AppData\Local\pip\Cache key: ${{ matrix.os }}-${{ matrix.python-version }}-pip diff --git a/.github/workflows/docker_update_readme.yml b/.github/workflows/docker_update_readme.yml index 822533ee2..ebb773ad7 100644 --- a/.github/workflows/docker_update_readme.yml +++ b/.github/workflows/docker_update_readme.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Docker Hub Description - uses: peter-evans/dockerhub-description@v3 + uses: peter-evans/dockerhub-description@v2.4.3 env: DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} diff --git a/docs/includes/pricing.md b/docs/includes/pricing.md index 103df6cd3..ed8a45e68 100644 --- a/docs/includes/pricing.md +++ b/docs/includes/pricing.md @@ -51,9 +51,9 @@ When buying with the orderbook enabled (`bid_strategy.use_order_book=True`), Fre #### Buy price without Orderbook enabled -The following section uses `side` as the configured `bid_strategy.price_side` (defaults to `"bid"`). +The following section uses `side` as the configured `bid_strategy.price_side`. -When not using orderbook (`bid_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's below the `last` traded price from the ticker. Otherwise (when the `side` price is above the `last` price), it calculates a rate between `side` and `last` price based on `bid_strategy.ask_last_balance`.. +When not using orderbook (`bid_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's below the `last` traded price from the ticker. Otherwise (when the `side` price is above the `last` price), it calculates a rate between `side` and `last` price. The `bid_strategy.ask_last_balance` configuration parameter controls this. A value of `0.0` will use `side` price, while `1.0` will use the `last` price and values between those interpolate between ask and last price. @@ -88,9 +88,9 @@ When selling with the orderbook enabled (`ask_strategy.use_order_book=True`), Fr #### Sell price without Orderbook enabled -The following section uses `side` as the configured `ask_strategy.price_side` (defaults to `"ask"`). +When not using orderbook (`ask_strategy.use_order_book=False`), the price at the `ask_strategy.price_side` side (defaults to `"ask"`) from the ticker will be used as the sell price. -When not using orderbook (`ask_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's above the `last` traded price from the ticker. Otherwise (when the `side` price is below the `last` price), it calculates a rate between `side` and `last` price based on `ask_strategy.bid_last_balance`. +When not using orderbook (`ask_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's below the `last` traded price from the ticker. Otherwise (when the `side` price is above the `last` price), it calculates a rate between `side` and `last` price. The `ask_strategy.bid_last_balance` configuration parameter controls this. A value of `0.0` will use `side` price, while `1.0` will use the last price and values between those interpolate between `side` and last price. diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 1f7db75c5..0ca0e4b63 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,4 @@ -mkdocs==1.3.0 -mkdocs-material==8.2.8 +mkdocs==1.2.3 +mkdocs-material==8.2.5 mdx_truly_sane_lists==1.2 -pymdown-extensions==9.3 -jinja2==3.1.1 +pymdown-extensions==9.2 diff --git a/docs/strategy-advanced.md b/docs/strategy-advanced.md index b1f154355..3793abacf 100644 --- a/docs/strategy-advanced.md +++ b/docs/strategy-advanced.md @@ -146,7 +146,7 @@ def version(self) -> str: The strategies can be derived from other strategies. This avoids duplication of your custom strategy code. You can use this technique to override small parts of your main strategy, leaving the rest untouched: -``` python title="user_data/strategies/myawesomestrategy.py" +``` python class MyAwesomeStrategy(IStrategy): ... stoploss = 0.13 @@ -155,10 +155,6 @@ class MyAwesomeStrategy(IStrategy): # should be in any custom strategy... ... -``` - -``` python title="user_data/strategies/MyAwesomeStrategy2.py" -from myawesomestrategy import MyAwesomeStrategy class MyAwesomeStrategy2(MyAwesomeStrategy): # Override something stoploss = 0.08 @@ -167,7 +163,16 @@ class MyAwesomeStrategy2(MyAwesomeStrategy): Both attributes and methods may be overridden, altering behavior of the original strategy in a way you need. -While keeping the subclass in the same file is technically possible, it can lead to some problems with hyperopt parameter files, we therefore recommend to use separate strategy files, and import the parent strategy as shown above. +!!! Note "Parent-strategy in different files" + If you have the parent-strategy in a different file, you'll need to add the following to the top of your "child"-file to ensure proper loading, otherwise freqtrade may not be able to load the parent strategy correctly. + + ``` python + import sys + from pathlib import Path + sys.path.append(str(Path(__file__).parent)) + + from myawesomestrategy import MyAwesomeStrategy + ``` ## Embedding Strategies diff --git a/freqtrade/__init__.py b/freqtrade/__init__.py index f8be8f66f..2747efc96 100644 --- a/freqtrade/__init__.py +++ b/freqtrade/__init__.py @@ -1,14 +1,27 @@ """ Freqtrade bot """ __version__ = 'develop' -if 'dev' in __version__: +if __version__ == 'develop': + try: import subprocess - __version__ = __version__ + '-' + subprocess.check_output( + __version__ = 'develop-' + subprocess.check_output( ['git', 'log', '--format="%h"', '-n 1'], stderr=subprocess.DEVNULL).decode("utf-8").rstrip().strip('"') + # from datetime import datetime + # last_release = subprocess.check_output( + # ['git', 'tag'] + # ).decode('utf-8').split()[-1].split(".") + # # Releases are in the format "2020.1" - we increment the latest version for dev. + # prefix = f"{last_release[0]}.{int(last_release[1]) + 1}" + # dev_version = int(datetime.now().timestamp() // 1000) + # __version__ = f"{prefix}.dev{dev_version}" + + # subprocess.check_output( + # ['git', 'log', '--format="%h"', '-n 1'], + # stderr=subprocess.DEVNULL).decode("utf-8").rstrip().strip('"') except Exception: # pragma: no cover # git not available, ignore try: diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 223673113..35f382469 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -32,24 +32,20 @@ from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss # noqa: F4 from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer from freqtrade.optimize.optimize_reports import generate_strategy_stats from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver -import matplotlib.pyplot as plt -import numpy as np -import random + # Suppress scikit-learn FutureWarnings from skopt with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=FutureWarning) from skopt import Optimizer from skopt.space import Dimension - from sklearn.model_selection import cross_val_score - from skopt.plots import plot_convergence, plot_regret, plot_evaluations, plot_objective progressbar.streams.wrap_stderr() progressbar.streams.wrap_stdout() logger = logging.getLogger(__name__) -INITIAL_POINTS = 32 +INITIAL_POINTS = 30 # Keep no more than SKOPT_MODEL_QUEUE_SIZE models # in the skopt model queue, to optimize memory consumption @@ -413,35 +409,6 @@ class Hyperopt: f'({(self.max_date - self.min_date).days} days)..') # Store non-trimmed data - will be trimmed after signal generation. dump(preprocessed, self.data_pickle_file) - - def get_asked_points(self, n_points: int) -> List[List[Any]]: - ''' - Enforce points returned from `self.opt.ask` have not been already evaluated - - Steps: - 1. Try to get points using `self.opt.ask` first - 2. Discard the points that have already been evaluated - 3. Retry using `self.opt.ask` up to 3 times - 4. If still some points are missing in respect to `n_points`, random sample some points - 5. Repeat until at least `n_points` points in the `asked_non_tried` list - 6. Return a list with length truncated at `n_points` - ''' - i = 0 - asked_non_tried: List[List[Any]] = [] - while i < 100 and len(asked_non_tried) < n_points: - if i < 3: - self.opt.cache_ = {} - asked = self.opt.ask(n_points=n_points * 5) - else: - asked = self.opt.space.rvs(n_samples=n_points * 5) - asked_non_tried += [x for x in asked - if x not in self.opt.Xi - and x not in asked_non_tried] - i += 1 - if asked_non_tried: - return asked_non_tried[:min(len(asked_non_tried), n_points)] - else: - return self.opt.ask(n_points=n_points) def get_asked_points(self, n_points: int) -> Tuple[List[List[Any]], List[bool]]: ''' @@ -548,13 +515,7 @@ class Hyperopt: asked, is_random = self.get_asked_points(n_points=current_jobs) f_val = self.run_optimizer_parallel(parallel, asked, i) - res = self.opt.tell(asked, [v['loss'] for v in f_val]) - - self.plot_optimizer(res, path='user_data/scripts', convergence=False, regret=False, r2=False, objective=True, jobs=jobs) - - if res.models and hasattr(res.models[-1], "kernel_"): - print(f'kernel: {res.models[-1].kernel_}') - print(datetime.now()) + self.opt.tell(asked, [v['loss'] for v in f_val]) # Calculate progressbar outputs for j, val in enumerate(f_val): @@ -600,47 +561,3 @@ class Hyperopt: # This is printed when Ctrl+C is pressed quickly, before first epochs have # a chance to be evaluated. print("No epochs evaluated yet, no best result.") - - def plot_r2(self, res, ax, jobs): - if len(res.x_iters) < 10: - return - - if not hasattr(self, 'r2_list'): - self.r2_list = [] - - model = res.models[-1] - model.criterion = 'squared_error' - - r2 = cross_val_score(model, X=res.x_iters, y=res.func_vals, scoring='r2', cv=5, n_jobs=jobs).mean() - r2 = r2 if r2 > -5 else -5 - self.r2_list.append(r2) - - ax.plot(range(INITIAL_POINTS, INITIAL_POINTS + jobs * len(self.r2_list), jobs), self.r2_list, label='R2', marker=".", markersize=12, lw=2) - - def plot_optimizer(self, res, path, jobs, convergence=True, regret=True, evaluations=True, objective=True, r2=True): - path = Path(path) - if convergence: - ax = plot_convergence(res) - ax.flatten()[0].figure.savefig(path / 'convergence.png') - - if regret: - ax = plot_regret(res) - ax.flatten()[0].figure.savefig(path / 'regret.png') - - if evaluations: -# print('evaluations') - ax = plot_evaluations(res) - ax.flatten()[0].figure.savefig(path / 'evaluations.png') - - if objective and res.models: -# print('objective') - ax = plot_objective(res, sample_source='result', n_samples=50, n_points=10) - ax.flatten()[0].figure.savefig(path / 'objective.png') - - if r2 and res.models: - fig, ax = plt.subplots() - ax.set_ylabel('R2') - ax.set_xlabel('Epoch') - ax.set_title('R2') - ax = self.plot_r2(res, ax, jobs) - fig.savefig(path / 'r2.png') diff --git a/freqtrade/resolvers/iresolver.py b/freqtrade/resolvers/iresolver.py index 3ab461041..c6f97c976 100644 --- a/freqtrade/resolvers/iresolver.py +++ b/freqtrade/resolvers/iresolver.py @@ -6,7 +6,6 @@ This module load custom objects import importlib.util import inspect import logging -import sys from pathlib import Path from typing import Any, Dict, Iterator, List, Optional, Tuple, Type, Union @@ -16,22 +15,6 @@ from freqtrade.exceptions import OperationalException logger = logging.getLogger(__name__) -class PathModifier: - def __init__(self, path: Path): - self.path = path - - def __enter__(self): - """Inject path to allow importing with relative imports.""" - sys.path.insert(0, str(self.path)) - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - """Undo insertion of local path.""" - str_path = str(self.path) - if str_path in sys.path: - sys.path.remove(str_path) - - class IResolver: """ This class contains all the logic to load custom classes @@ -74,32 +57,27 @@ class IResolver: # Generate spec based on absolute path # Pass object_name as first argument to have logging print a reasonable name. - with PathModifier(module_path.parent): - module_name = module_path.stem or "" - spec = importlib.util.spec_from_file_location(module_name, str(module_path)) - if not spec: + spec = importlib.util.spec_from_file_location(object_name or "", str(module_path)) + if not spec: + return iter([None]) + + module = importlib.util.module_from_spec(spec) + try: + spec.loader.exec_module(module) # type: ignore # importlib does not use typehints + except (ModuleNotFoundError, SyntaxError, ImportError, NameError) as err: + # Catch errors in case a specific module is not installed + logger.warning(f"Could not import {module_path} due to '{err}'") + if enum_failed: return iter([None]) - module = importlib.util.module_from_spec(spec) - try: - spec.loader.exec_module(module) # type: ignore # importlib does not use typehints - except (ModuleNotFoundError, SyntaxError, ImportError, NameError) as err: - # Catch errors in case a specific module is not installed - logger.warning(f"Could not import {module_path} due to '{err}'") - if enum_failed: - return iter([None]) - - valid_objects_gen = ( - (obj, inspect.getsource(module)) for - name, obj in inspect.getmembers( - module, inspect.isclass) if ((object_name is None or object_name == name) - and issubclass(obj, cls.object_type) - and obj is not cls.object_type - and obj.__module__ == module_name - ) - ) - # The __module__ check ensures we only use strategies that are defined in this folder. - return valid_objects_gen + valid_objects_gen = ( + (obj, inspect.getsource(module)) for + name, obj in inspect.getmembers( + module, inspect.isclass) if ((object_name is None or object_name == name) + and issubclass(obj, cls.object_type) + and obj is not cls.object_type) + ) + return valid_objects_gen @classmethod def _search_object(cls, directory: Path, *, object_name: str, add_source: bool = False diff --git a/requirements-dev.txt b/requirements-dev.txt index 063cfaa45..c2f3eae8a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,9 +6,9 @@ coveralls==3.3.1 flake8==4.0.1 flake8-tidy-imports==4.6.0 -mypy==0.942 -pytest==7.1.1 -pytest-asyncio==0.18.3 +mypy==0.940 +pytest==7.1.0 +pytest-asyncio==0.18.2 pytest-cov==3.0.0 pytest-mock==3.7.0 pytest-random-order==1.0.4 @@ -22,8 +22,8 @@ nbconvert==6.4.4 # mypy types types-cachetools==5.0.0 types-filelock==3.2.5 -types-requests==2.27.15 -types-tabulate==0.8.6 +types-requests==2.27.12 +types-tabulate==0.8.5 # Extensions to datetime library -types-python-dateutil==2.8.10 \ No newline at end of file +types-python-dateutil==2.8.9 \ No newline at end of file diff --git a/requirements-hyperopt.txt b/requirements-hyperopt.txt index ad85ac71a..aeb7be035 100644 --- a/requirements-hyperopt.txt +++ b/requirements-hyperopt.txt @@ -8,4 +8,3 @@ scikit-optimize==0.9.0 filelock==3.6.0 joblib==1.1.0 progressbar2==4.0.0 -matplotlib \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index de05b3f7c..f0f030e78 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,22 +2,22 @@ numpy==1.22.3 pandas==1.4.1 pandas-ta==0.3.14b -ccxt==1.77.36 +ccxt==1.76.5 # Pin cryptography for now due to rust build errors with piwheels -cryptography==36.0.2 +cryptography==36.0.1 aiohttp==3.8.1 SQLAlchemy==1.4.32 python-telegram-bot==13.11 arrow==1.2.2 cachetools==4.2.2 requests==2.27.1 -urllib3==1.26.9 +urllib3==1.26.8 jsonschema==4.4.0 TA-Lib==0.4.24 technical==1.3.0 tabulate==0.8.9 pycoingecko==2.2.0 -jinja2==3.1.1 +jinja2==3.0.3 tables==3.7.0 blosc==1.10.6 diff --git a/tests/conftest.py b/tests/conftest.py index 809342c03..1dd6e8869 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1019,8 +1019,8 @@ def limit_buy_order_open(): 'type': 'limit', 'side': 'buy', 'symbol': 'mocked', - 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), + 'timestamp': arrow.utcnow().int_timestamp, 'price': 0.00001099, 'amount': 90.99181073, 'filled': 0.0, @@ -1046,7 +1046,6 @@ def market_buy_order(): 'type': 'market', 'side': 'buy', 'symbol': 'mocked', - 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 0.00004099, 'amount': 91.99181073, @@ -1063,7 +1062,6 @@ def market_sell_order(): 'type': 'market', 'side': 'sell', 'symbol': 'mocked', - 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 0.00004173, 'amount': 91.99181073, @@ -1080,8 +1078,7 @@ def limit_buy_order_old(): 'type': 'limit', 'side': 'buy', 'symbol': 'mocked', - 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, + 'datetime': str(arrow.utcnow().shift(minutes=-601).datetime), 'price': 0.00001099, 'amount': 90.99181073, 'filled': 0.0, @@ -1097,7 +1094,6 @@ def limit_sell_order_old(): 'type': 'limit', 'side': 'sell', 'symbol': 'ETH/BTC', - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'price': 0.00001099, 'amount': 90.99181073, @@ -1114,7 +1110,6 @@ def limit_buy_order_old_partial(): 'type': 'limit', 'side': 'buy', 'symbol': 'ETH/BTC', - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'price': 0.00001099, 'amount': 90.99181073, @@ -1144,7 +1139,7 @@ def limit_buy_order_canceled_empty(request): 'info': {}, 'id': '1234512345', 'clientOrderId': None, - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'lastTradeTimestamp': None, 'symbol': 'LTC/USDT', @@ -1165,7 +1160,7 @@ def limit_buy_order_canceled_empty(request): 'info': {}, 'id': 'AZNPFF-4AC4N-7MKTAT', 'clientOrderId': None, - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'lastTradeTimestamp': None, 'status': 'canceled', @@ -1186,7 +1181,7 @@ def limit_buy_order_canceled_empty(request): 'info': {}, 'id': '1234512345', 'clientOrderId': 'alb1234123', - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'lastTradeTimestamp': None, 'symbol': 'LTC/USDT', @@ -1207,7 +1202,7 @@ def limit_buy_order_canceled_empty(request): 'info': {}, 'id': '1234512345', 'clientOrderId': 'alb1234123', - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'lastTradeTimestamp': None, 'symbol': 'LTC/USDT', @@ -1233,7 +1228,7 @@ def limit_sell_order_open(): 'side': 'sell', 'symbol': 'mocked', 'datetime': arrow.utcnow().isoformat(), - 'timestamp': arrow.utcnow().int_timestamp * 1000, + 'timestamp': arrow.utcnow().int_timestamp, 'price': 0.00001173, 'amount': 90.99181073, 'filled': 0.0, @@ -1399,7 +1394,7 @@ def tickers(): 'BLK/BTC': { 'symbol': 'BLK/BTC', 'timestamp': 1522014806072, - 'datetime': '2018-03-25T21:53:26.072Z', + 'datetime': '2018-03-25T21:53:26.720Z', 'high': 0.007745, 'low': 0.007512, 'bid': 0.007729, @@ -1895,8 +1890,7 @@ def buy_order_fee(): 'type': 'limit', 'side': 'buy', 'symbol': 'mocked', - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, - 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), + 'datetime': str(arrow.utcnow().shift(minutes=-601).datetime), 'price': 0.245441, 'amount': 8.0, 'cost': 1.963528, @@ -2205,7 +2199,7 @@ def limit_buy_order_usdt_open(): 'side': 'buy', 'symbol': 'mocked', 'datetime': arrow.utcnow().isoformat(), - 'timestamp': arrow.utcnow().int_timestamp * 1000, + 'timestamp': arrow.utcnow().int_timestamp, 'price': 2.00, 'amount': 30.0, 'filled': 0.0, @@ -2232,7 +2226,7 @@ def limit_sell_order_usdt_open(): 'side': 'sell', 'symbol': 'mocked', 'datetime': arrow.utcnow().isoformat(), - 'timestamp': arrow.utcnow().int_timestamp * 1000, + 'timestamp': arrow.utcnow().int_timestamp, 'price': 2.20, 'amount': 30.0, 'filled': 0.0, @@ -2257,7 +2251,6 @@ def market_buy_order_usdt(): 'type': 'market', 'side': 'buy', 'symbol': 'mocked', - 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 2.00, 'amount': 30.0, @@ -2314,7 +2307,6 @@ def market_sell_order_usdt(): 'type': 'market', 'side': 'sell', 'symbol': 'mocked', - 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 2.20, 'amount': 30.0, diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index b76cb23e6..ff8383997 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1098,7 +1098,7 @@ def test_create_order(default_conf, mocker, side, ordertype, rate, marketprice, exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) order = exchange.create_order( - pair='ETH/BTC', ordertype=ordertype, side=side, amount=1, rate=rate) + pair='ETH/BTC', ordertype=ordertype, side=side, amount=1, rate=200) assert 'id' in order assert 'info' in order diff --git a/tests/strategy/strats/hyperoptable_strategy.py b/tests/strategy/strats/hyperoptable_strategy.py index dc6b03a3e..88bdd078e 100644 --- a/tests/strategy/strats/hyperoptable_strategy.py +++ b/tests/strategy/strats/hyperoptable_strategy.py @@ -1,13 +1,14 @@ # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement +import talib.abstract as ta from pandas import DataFrame -from strategy_test_v2 import StrategyTestV2 import freqtrade.vendor.qtpylib.indicators as qtpylib -from freqtrade.strategy import BooleanParameter, DecimalParameter, IntParameter, RealParameter +from freqtrade.strategy import (BooleanParameter, DecimalParameter, IntParameter, IStrategy, + RealParameter) -class HyperoptableStrategy(StrategyTestV2): +class HyperoptableStrategy(IStrategy): """ Default Strategy provided by freqtrade bot. Please do not modify this strategy, it's intended for internal use only. @@ -15,6 +16,38 @@ class HyperoptableStrategy(StrategyTestV2): or strategy repository https://github.com/freqtrade/freqtrade-strategies for samples and inspiration. """ + INTERFACE_VERSION = 2 + + # 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 ticker interval for the strategy + timeframe = '5m' + + # Optional order type mapping + order_types = { + 'buy': 'limit', + 'sell': '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 = { + 'buy': 'gtc', + 'sell': 'gtc', + } buy_params = { 'buy_rsi': 35, @@ -58,6 +91,55 @@ class HyperoptableStrategy(StrategyTestV2): """ return [] + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + """ + Adds several different TA indicators to the given DataFrame + + Performance Note: For the best performance be frugal on the number of indicators + you are using. Let uncomment only the indicator you are using in your strategies + or your hyperopt configuration, otherwise you will waste your memory and CPU usage. + :param dataframe: Dataframe with data from the exchange + :param metadata: Additional information, like the currently traded pair + :return: a Dataframe with all mandatory indicators for the strategies + """ + + # 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_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ Based on TA indicators, populates the buy signal for the given dataframe diff --git a/tests/strategy/strats/strategy_test_v2.py b/tests/strategy/strats/strategy_test_v2.py index 59f1f569e..c57becdad 100644 --- a/tests/strategy/strats/strategy_test_v2.py +++ b/tests/strategy/strats/strategy_test_v2.py @@ -7,7 +7,7 @@ from pandas import DataFrame import freqtrade.vendor.qtpylib.indicators as qtpylib from freqtrade.persistence import Trade -from freqtrade.strategy import IStrategy +from freqtrade.strategy.interface import IStrategy class StrategyTestV2(IStrategy): From 3e24d01af401dd1fbe11b9c3951a6e848f8af716 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Wed, 30 Mar 2022 09:41:40 +0100 Subject: [PATCH 025/159] fix flake8 --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 1dd6e8869..0387f0a22 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2089,7 +2089,7 @@ def saved_hyperopt_results(): 'params_details': {'buy': {'mfi-value': 13, 'fastd-value': 35, 'adx-value': 39, 'rsi-value': 29, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': True, 'trigger': 'macd_cross_signal'}, 'sell': {'sell-mfi-value': 87, 'sell-fastd-value': 54, 'sell-adx-value': 63, 'sell-rsi-value': 93, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper'}, 'roi': {0: 0.411946348378729, 215: 0.2052334363683207, 891: 0.06264755784937427, 2293: 0}, 'stoploss': {'stoploss': -0.11818343570194478}}, # noqa: E501 'results_metrics': {'total_trades': 0, 'wins': 0, 'draws': 0, 'losses': 0, 'profit_mean': None, 'profit_median': None, 'profit_total': 0, 'profit': 0.0, 'holding_avg': timedelta()}, # noqa: E501 'results_explanation': ' 0 trades. Avg profit nan%. Total profit 0.00000000 BTC ( 0.00Σ%). Avg duration nan min.', # noqa: E501 - 'total_profit': 0, 'current_epoch': 4, 'is_initial_point': True, 'is_random': False, 'is_best': False + 'total_profit': 0, 'current_epoch': 4, 'is_initial_point': True, 'is_random': False, 'is_best': False # noqa: E501 }, { 'loss': 0.22195522184191518, 'params_dict': {'mfi-value': 17, 'fastd-value': 21, 'adx-value': 38, 'rsi-value': 33, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': True, 'rsi-enabled': False, 'trigger': 'macd_cross_signal', 'sell-mfi-value': 87, 'sell-fastd-value': 82, 'sell-adx-value': 78, 'sell-rsi-value': 69, 'sell-mfi-enabled': True, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': False, 'sell-trigger': 'sell-macd_cross_signal', 'roi_t1': 1269, 'roi_t2': 601, 'roi_t3': 444, 'roi_p1': 0.07280999507931168, 'roi_p2': 0.08946698095898986, 'roi_p3': 0.1454876733325284, 'stoploss': -0.18181041180901014}, # noqa: E501 From bad179ebaa605927e956e2bf6e7d8391538b9f31 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Wed, 30 Mar 2022 09:48:10 +0100 Subject: [PATCH 026/159] fix merge mess This reverts commit 9f171193ef2b893b7f7c9269b9a2c6b796f0d71c. --- .github/workflows/ci.yml | 10 +-- .github/workflows/docker_update_readme.yml | 2 +- docs/includes/pricing.md | 8 +- docs/requirements-docs.txt | 7 +- docs/strategy-advanced.md | 17 ++-- freqtrade/__init__.py | 17 +--- freqtrade/resolvers/iresolver.py | 60 +++++++++---- requirements-dev.txt | 12 +-- requirements.txt | 8 +- tests/conftest.py | 30 ++++--- tests/exchange/test_exchange.py | 2 +- .../strategy/strats/hyperoptable_strategy.py | 88 +------------------ tests/strategy/strats/strategy_test_v2.py | 2 +- 13 files changed, 97 insertions(+), 166 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 216a53bc1..b8df7ab10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,14 +31,14 @@ jobs: python-version: ${{ matrix.python-version }} - name: Cache_dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 id: cache with: path: ~/dependencies/ key: ${{ runner.os }}-dependencies - name: pip cache (linux) - uses: actions/cache@v2 + uses: actions/cache@v3 if: runner.os == 'Linux' with: path: ~/.cache/pip @@ -126,14 +126,14 @@ jobs: python-version: ${{ matrix.python-version }} - name: Cache_dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 id: cache with: path: ~/dependencies/ key: ${{ runner.os }}-dependencies - name: pip cache (macOS) - uses: actions/cache@v2 + uses: actions/cache@v3 if: runner.os == 'macOS' with: path: ~/Library/Caches/pip @@ -218,7 +218,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Pip cache (Windows) - uses: actions/cache@preview + uses: actions/cache@v3 with: path: ~\AppData\Local\pip\Cache key: ${{ matrix.os }}-${{ matrix.python-version }}-pip diff --git a/.github/workflows/docker_update_readme.yml b/.github/workflows/docker_update_readme.yml index ebb773ad7..822533ee2 100644 --- a/.github/workflows/docker_update_readme.yml +++ b/.github/workflows/docker_update_readme.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Docker Hub Description - uses: peter-evans/dockerhub-description@v2.4.3 + uses: peter-evans/dockerhub-description@v3 env: DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} diff --git a/docs/includes/pricing.md b/docs/includes/pricing.md index ed8a45e68..103df6cd3 100644 --- a/docs/includes/pricing.md +++ b/docs/includes/pricing.md @@ -51,9 +51,9 @@ When buying with the orderbook enabled (`bid_strategy.use_order_book=True`), Fre #### Buy price without Orderbook enabled -The following section uses `side` as the configured `bid_strategy.price_side`. +The following section uses `side` as the configured `bid_strategy.price_side` (defaults to `"bid"`). -When not using orderbook (`bid_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's below the `last` traded price from the ticker. Otherwise (when the `side` price is above the `last` price), it calculates a rate between `side` and `last` price. +When not using orderbook (`bid_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's below the `last` traded price from the ticker. Otherwise (when the `side` price is above the `last` price), it calculates a rate between `side` and `last` price based on `bid_strategy.ask_last_balance`.. The `bid_strategy.ask_last_balance` configuration parameter controls this. A value of `0.0` will use `side` price, while `1.0` will use the `last` price and values between those interpolate between ask and last price. @@ -88,9 +88,9 @@ When selling with the orderbook enabled (`ask_strategy.use_order_book=True`), Fr #### Sell price without Orderbook enabled -When not using orderbook (`ask_strategy.use_order_book=False`), the price at the `ask_strategy.price_side` side (defaults to `"ask"`) from the ticker will be used as the sell price. +The following section uses `side` as the configured `ask_strategy.price_side` (defaults to `"ask"`). -When not using orderbook (`ask_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's below the `last` traded price from the ticker. Otherwise (when the `side` price is above the `last` price), it calculates a rate between `side` and `last` price. +When not using orderbook (`ask_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's above the `last` traded price from the ticker. Otherwise (when the `side` price is below the `last` price), it calculates a rate between `side` and `last` price based on `ask_strategy.bid_last_balance`. The `ask_strategy.bid_last_balance` configuration parameter controls this. A value of `0.0` will use `side` price, while `1.0` will use the last price and values between those interpolate between `side` and last price. diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 0ca0e4b63..1f7db75c5 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,4 +1,5 @@ -mkdocs==1.2.3 -mkdocs-material==8.2.5 +mkdocs==1.3.0 +mkdocs-material==8.2.8 mdx_truly_sane_lists==1.2 -pymdown-extensions==9.2 +pymdown-extensions==9.3 +jinja2==3.1.1 diff --git a/docs/strategy-advanced.md b/docs/strategy-advanced.md index 3793abacf..b1f154355 100644 --- a/docs/strategy-advanced.md +++ b/docs/strategy-advanced.md @@ -146,7 +146,7 @@ def version(self) -> str: The strategies can be derived from other strategies. This avoids duplication of your custom strategy code. You can use this technique to override small parts of your main strategy, leaving the rest untouched: -``` python +``` python title="user_data/strategies/myawesomestrategy.py" class MyAwesomeStrategy(IStrategy): ... stoploss = 0.13 @@ -155,6 +155,10 @@ class MyAwesomeStrategy(IStrategy): # should be in any custom strategy... ... +``` + +``` python title="user_data/strategies/MyAwesomeStrategy2.py" +from myawesomestrategy import MyAwesomeStrategy class MyAwesomeStrategy2(MyAwesomeStrategy): # Override something stoploss = 0.08 @@ -163,16 +167,7 @@ class MyAwesomeStrategy2(MyAwesomeStrategy): Both attributes and methods may be overridden, altering behavior of the original strategy in a way you need. -!!! Note "Parent-strategy in different files" - If you have the parent-strategy in a different file, you'll need to add the following to the top of your "child"-file to ensure proper loading, otherwise freqtrade may not be able to load the parent strategy correctly. - - ``` python - import sys - from pathlib import Path - sys.path.append(str(Path(__file__).parent)) - - from myawesomestrategy import MyAwesomeStrategy - ``` +While keeping the subclass in the same file is technically possible, it can lead to some problems with hyperopt parameter files, we therefore recommend to use separate strategy files, and import the parent strategy as shown above. ## Embedding Strategies diff --git a/freqtrade/__init__.py b/freqtrade/__init__.py index 2747efc96..f8be8f66f 100644 --- a/freqtrade/__init__.py +++ b/freqtrade/__init__.py @@ -1,27 +1,14 @@ """ Freqtrade bot """ __version__ = 'develop' -if __version__ == 'develop': - +if 'dev' in __version__: try: import subprocess - __version__ = 'develop-' + subprocess.check_output( + __version__ = __version__ + '-' + subprocess.check_output( ['git', 'log', '--format="%h"', '-n 1'], stderr=subprocess.DEVNULL).decode("utf-8").rstrip().strip('"') - # from datetime import datetime - # last_release = subprocess.check_output( - # ['git', 'tag'] - # ).decode('utf-8').split()[-1].split(".") - # # Releases are in the format "2020.1" - we increment the latest version for dev. - # prefix = f"{last_release[0]}.{int(last_release[1]) + 1}" - # dev_version = int(datetime.now().timestamp() // 1000) - # __version__ = f"{prefix}.dev{dev_version}" - - # subprocess.check_output( - # ['git', 'log', '--format="%h"', '-n 1'], - # stderr=subprocess.DEVNULL).decode("utf-8").rstrip().strip('"') except Exception: # pragma: no cover # git not available, ignore try: diff --git a/freqtrade/resolvers/iresolver.py b/freqtrade/resolvers/iresolver.py index c6f97c976..3ab461041 100644 --- a/freqtrade/resolvers/iresolver.py +++ b/freqtrade/resolvers/iresolver.py @@ -6,6 +6,7 @@ This module load custom objects import importlib.util import inspect import logging +import sys from pathlib import Path from typing import Any, Dict, Iterator, List, Optional, Tuple, Type, Union @@ -15,6 +16,22 @@ from freqtrade.exceptions import OperationalException logger = logging.getLogger(__name__) +class PathModifier: + def __init__(self, path: Path): + self.path = path + + def __enter__(self): + """Inject path to allow importing with relative imports.""" + sys.path.insert(0, str(self.path)) + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Undo insertion of local path.""" + str_path = str(self.path) + if str_path in sys.path: + sys.path.remove(str_path) + + class IResolver: """ This class contains all the logic to load custom classes @@ -57,27 +74,32 @@ class IResolver: # Generate spec based on absolute path # Pass object_name as first argument to have logging print a reasonable name. - spec = importlib.util.spec_from_file_location(object_name or "", str(module_path)) - if not spec: - return iter([None]) - - module = importlib.util.module_from_spec(spec) - try: - spec.loader.exec_module(module) # type: ignore # importlib does not use typehints - except (ModuleNotFoundError, SyntaxError, ImportError, NameError) as err: - # Catch errors in case a specific module is not installed - logger.warning(f"Could not import {module_path} due to '{err}'") - if enum_failed: + with PathModifier(module_path.parent): + module_name = module_path.stem or "" + spec = importlib.util.spec_from_file_location(module_name, str(module_path)) + if not spec: return iter([None]) - valid_objects_gen = ( - (obj, inspect.getsource(module)) for - name, obj in inspect.getmembers( - module, inspect.isclass) if ((object_name is None or object_name == name) - and issubclass(obj, cls.object_type) - and obj is not cls.object_type) - ) - return valid_objects_gen + module = importlib.util.module_from_spec(spec) + try: + spec.loader.exec_module(module) # type: ignore # importlib does not use typehints + except (ModuleNotFoundError, SyntaxError, ImportError, NameError) as err: + # Catch errors in case a specific module is not installed + logger.warning(f"Could not import {module_path} due to '{err}'") + if enum_failed: + return iter([None]) + + valid_objects_gen = ( + (obj, inspect.getsource(module)) for + name, obj in inspect.getmembers( + module, inspect.isclass) if ((object_name is None or object_name == name) + and issubclass(obj, cls.object_type) + and obj is not cls.object_type + and obj.__module__ == module_name + ) + ) + # The __module__ check ensures we only use strategies that are defined in this folder. + return valid_objects_gen @classmethod def _search_object(cls, directory: Path, *, object_name: str, add_source: bool = False diff --git a/requirements-dev.txt b/requirements-dev.txt index c2f3eae8a..063cfaa45 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,9 +6,9 @@ coveralls==3.3.1 flake8==4.0.1 flake8-tidy-imports==4.6.0 -mypy==0.940 -pytest==7.1.0 -pytest-asyncio==0.18.2 +mypy==0.942 +pytest==7.1.1 +pytest-asyncio==0.18.3 pytest-cov==3.0.0 pytest-mock==3.7.0 pytest-random-order==1.0.4 @@ -22,8 +22,8 @@ nbconvert==6.4.4 # mypy types types-cachetools==5.0.0 types-filelock==3.2.5 -types-requests==2.27.12 -types-tabulate==0.8.5 +types-requests==2.27.15 +types-tabulate==0.8.6 # Extensions to datetime library -types-python-dateutil==2.8.9 \ No newline at end of file +types-python-dateutil==2.8.10 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index f0f030e78..de05b3f7c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,22 +2,22 @@ numpy==1.22.3 pandas==1.4.1 pandas-ta==0.3.14b -ccxt==1.76.5 +ccxt==1.77.36 # Pin cryptography for now due to rust build errors with piwheels -cryptography==36.0.1 +cryptography==36.0.2 aiohttp==3.8.1 SQLAlchemy==1.4.32 python-telegram-bot==13.11 arrow==1.2.2 cachetools==4.2.2 requests==2.27.1 -urllib3==1.26.8 +urllib3==1.26.9 jsonschema==4.4.0 TA-Lib==0.4.24 technical==1.3.0 tabulate==0.8.9 pycoingecko==2.2.0 -jinja2==3.0.3 +jinja2==3.1.1 tables==3.7.0 blosc==1.10.6 diff --git a/tests/conftest.py b/tests/conftest.py index 0387f0a22..b15716fcc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1019,8 +1019,8 @@ def limit_buy_order_open(): 'type': 'limit', 'side': 'buy', 'symbol': 'mocked', + 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), - 'timestamp': arrow.utcnow().int_timestamp, 'price': 0.00001099, 'amount': 90.99181073, 'filled': 0.0, @@ -1046,6 +1046,7 @@ def market_buy_order(): 'type': 'market', 'side': 'buy', 'symbol': 'mocked', + 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 0.00004099, 'amount': 91.99181073, @@ -1062,6 +1063,7 @@ def market_sell_order(): 'type': 'market', 'side': 'sell', 'symbol': 'mocked', + 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 0.00004173, 'amount': 91.99181073, @@ -1078,7 +1080,8 @@ def limit_buy_order_old(): 'type': 'limit', 'side': 'buy', 'symbol': 'mocked', - 'datetime': str(arrow.utcnow().shift(minutes=-601).datetime), + 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'price': 0.00001099, 'amount': 90.99181073, 'filled': 0.0, @@ -1094,6 +1097,7 @@ def limit_sell_order_old(): 'type': 'limit', 'side': 'sell', 'symbol': 'ETH/BTC', + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'price': 0.00001099, 'amount': 90.99181073, @@ -1110,6 +1114,7 @@ def limit_buy_order_old_partial(): 'type': 'limit', 'side': 'buy', 'symbol': 'ETH/BTC', + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'price': 0.00001099, 'amount': 90.99181073, @@ -1139,7 +1144,7 @@ def limit_buy_order_canceled_empty(request): 'info': {}, 'id': '1234512345', 'clientOrderId': None, - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp, + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'lastTradeTimestamp': None, 'symbol': 'LTC/USDT', @@ -1160,7 +1165,7 @@ def limit_buy_order_canceled_empty(request): 'info': {}, 'id': 'AZNPFF-4AC4N-7MKTAT', 'clientOrderId': None, - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp, + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'lastTradeTimestamp': None, 'status': 'canceled', @@ -1181,7 +1186,7 @@ def limit_buy_order_canceled_empty(request): 'info': {}, 'id': '1234512345', 'clientOrderId': 'alb1234123', - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp, + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'lastTradeTimestamp': None, 'symbol': 'LTC/USDT', @@ -1202,7 +1207,7 @@ def limit_buy_order_canceled_empty(request): 'info': {}, 'id': '1234512345', 'clientOrderId': 'alb1234123', - 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp, + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'lastTradeTimestamp': None, 'symbol': 'LTC/USDT', @@ -1228,7 +1233,7 @@ def limit_sell_order_open(): 'side': 'sell', 'symbol': 'mocked', 'datetime': arrow.utcnow().isoformat(), - 'timestamp': arrow.utcnow().int_timestamp, + 'timestamp': arrow.utcnow().int_timestamp * 1000, 'price': 0.00001173, 'amount': 90.99181073, 'filled': 0.0, @@ -1394,7 +1399,7 @@ def tickers(): 'BLK/BTC': { 'symbol': 'BLK/BTC', 'timestamp': 1522014806072, - 'datetime': '2018-03-25T21:53:26.720Z', + 'datetime': '2018-03-25T21:53:26.072Z', 'high': 0.007745, 'low': 0.007512, 'bid': 0.007729, @@ -1890,7 +1895,8 @@ def buy_order_fee(): 'type': 'limit', 'side': 'buy', 'symbol': 'mocked', - 'datetime': str(arrow.utcnow().shift(minutes=-601).datetime), + 'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000, + 'datetime': arrow.utcnow().shift(minutes=-601).isoformat(), 'price': 0.245441, 'amount': 8.0, 'cost': 1.963528, @@ -2199,7 +2205,7 @@ def limit_buy_order_usdt_open(): 'side': 'buy', 'symbol': 'mocked', 'datetime': arrow.utcnow().isoformat(), - 'timestamp': arrow.utcnow().int_timestamp, + 'timestamp': arrow.utcnow().int_timestamp * 1000, 'price': 2.00, 'amount': 30.0, 'filled': 0.0, @@ -2226,7 +2232,7 @@ def limit_sell_order_usdt_open(): 'side': 'sell', 'symbol': 'mocked', 'datetime': arrow.utcnow().isoformat(), - 'timestamp': arrow.utcnow().int_timestamp, + 'timestamp': arrow.utcnow().int_timestamp * 1000, 'price': 2.20, 'amount': 30.0, 'filled': 0.0, @@ -2251,6 +2257,7 @@ def market_buy_order_usdt(): 'type': 'market', 'side': 'buy', 'symbol': 'mocked', + 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 2.00, 'amount': 30.0, @@ -2307,6 +2314,7 @@ def market_sell_order_usdt(): 'type': 'market', 'side': 'sell', 'symbol': 'mocked', + 'timestamp': arrow.utcnow().int_timestamp * 1000, 'datetime': arrow.utcnow().isoformat(), 'price': 2.20, 'amount': 30.0, diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index ff8383997..b76cb23e6 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1098,7 +1098,7 @@ def test_create_order(default_conf, mocker, side, ordertype, rate, marketprice, exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) order = exchange.create_order( - pair='ETH/BTC', ordertype=ordertype, side=side, amount=1, rate=200) + pair='ETH/BTC', ordertype=ordertype, side=side, amount=1, rate=rate) assert 'id' in order assert 'info' in order diff --git a/tests/strategy/strats/hyperoptable_strategy.py b/tests/strategy/strats/hyperoptable_strategy.py index 88bdd078e..dc6b03a3e 100644 --- a/tests/strategy/strats/hyperoptable_strategy.py +++ b/tests/strategy/strats/hyperoptable_strategy.py @@ -1,14 +1,13 @@ # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement -import talib.abstract as ta from pandas import DataFrame +from strategy_test_v2 import StrategyTestV2 import freqtrade.vendor.qtpylib.indicators as qtpylib -from freqtrade.strategy import (BooleanParameter, DecimalParameter, IntParameter, IStrategy, - RealParameter) +from freqtrade.strategy import BooleanParameter, DecimalParameter, IntParameter, RealParameter -class HyperoptableStrategy(IStrategy): +class HyperoptableStrategy(StrategyTestV2): """ Default Strategy provided by freqtrade bot. Please do not modify this strategy, it's intended for internal use only. @@ -16,38 +15,6 @@ class HyperoptableStrategy(IStrategy): or strategy repository https://github.com/freqtrade/freqtrade-strategies for samples and inspiration. """ - INTERFACE_VERSION = 2 - - # 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 ticker interval for the strategy - timeframe = '5m' - - # Optional order type mapping - order_types = { - 'buy': 'limit', - 'sell': '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 = { - 'buy': 'gtc', - 'sell': 'gtc', - } buy_params = { 'buy_rsi': 35, @@ -91,55 +58,6 @@ class HyperoptableStrategy(IStrategy): """ return [] - def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - """ - Adds several different TA indicators to the given DataFrame - - Performance Note: For the best performance be frugal on the number of indicators - you are using. Let uncomment only the indicator you are using in your strategies - or your hyperopt configuration, otherwise you will waste your memory and CPU usage. - :param dataframe: Dataframe with data from the exchange - :param metadata: Additional information, like the currently traded pair - :return: a Dataframe with all mandatory indicators for the strategies - """ - - # 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_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ Based on TA indicators, populates the buy signal for the given dataframe diff --git a/tests/strategy/strats/strategy_test_v2.py b/tests/strategy/strats/strategy_test_v2.py index c57becdad..59f1f569e 100644 --- a/tests/strategy/strats/strategy_test_v2.py +++ b/tests/strategy/strats/strategy_test_v2.py @@ -7,7 +7,7 @@ from pandas import DataFrame import freqtrade.vendor.qtpylib.indicators as qtpylib from freqtrade.persistence import Trade -from freqtrade.strategy.interface import IStrategy +from freqtrade.strategy import IStrategy class StrategyTestV2(IStrategy): From e85c7ca8ff18f7f139ddef49a0d21a5a71ecd058 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Wed, 30 Mar 2022 09:50:37 +0100 Subject: [PATCH 027/159] remove blank line --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 03a9da87b..b116b261f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,6 @@ numpy==1.22.3 pandas==1.4.1 pandas-ta==0.3.14b - ccxt==1.77.45 # Pin cryptography for now due to rust build errors with piwheels cryptography==36.0.2 From 6df15a7af9aa59740af1802fd4e2b7da02132279 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 19 Mar 2022 18:54:11 -0600 Subject: [PATCH 028/159] Recursively search subdirectories in user_data/strategies for a strategy --- freqtrade/resolvers/iresolver.py | 13 +++++++++---- freqtrade/resolvers/strategy_resolver.py | 10 ++++++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/freqtrade/resolvers/iresolver.py b/freqtrade/resolvers/iresolver.py index 3ab461041..cddc8b84d 100644 --- a/freqtrade/resolvers/iresolver.py +++ b/freqtrade/resolvers/iresolver.py @@ -44,7 +44,7 @@ class IResolver: @classmethod def build_search_paths(cls, config: Dict[str, Any], user_subdir: Optional[str] = None, - extra_dir: Optional[str] = None) -> List[Path]: + extra_dirs: Optional[List[str]] = None) -> List[Path]: abs_paths: List[Path] = [] if cls.initial_search_path: @@ -53,9 +53,10 @@ class IResolver: if user_subdir: abs_paths.insert(0, config['user_data_dir'].joinpath(user_subdir)) - if extra_dir: + if extra_dirs: # Add extra directory to the top of the search paths - abs_paths.insert(0, Path(extra_dir).resolve()) + for dir in extra_dirs: + abs_paths.insert(0, Path(dir).resolve()) return abs_paths @@ -164,9 +165,13 @@ class IResolver: :return: Object instance or None """ + extra_dirs: List[str] = [] + if extra_dir: + extra_dirs.append(extra_dir) + abs_paths = cls.build_search_paths(config, user_subdir=cls.user_subdir, - extra_dir=extra_dir) + extra_dirs=extra_dirs) found_object = cls._load_object(paths=abs_paths, object_name=object_name, kwargs=kwargs) diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index 8ad7cdb59..4f5d22e45 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -7,8 +7,9 @@ import logging import tempfile from base64 import urlsafe_b64decode from inspect import getfullargspec +from os import walk from pathlib import Path -from typing import Any, Dict, Optional +from typing import Any, Dict, List, Optional from freqtrade.constants import REQUIRED_ORDERTIF, REQUIRED_ORDERTYPES, USERPATH_STRATEGIES from freqtrade.exceptions import OperationalException @@ -166,10 +167,15 @@ class StrategyResolver(IResolver): :param extra_dir: additional directory to search for the given strategy :return: Strategy instance or None """ + extra_dirs: List[str] = [ + path[0] for path in walk(f"{config['user_data_dir']}/{USERPATH_STRATEGIES}") + ] # sub-directories + if extra_dir: + extra_dirs.append(extra_dir) abs_paths = StrategyResolver.build_search_paths(config, user_subdir=USERPATH_STRATEGIES, - extra_dir=extra_dir) + extra_dirs=extra_dirs) if ":" in strategy_name: logger.info("loading base64 encoded strategy") From 185daf5772fc1e42d014898eedc8bbbebd4bcfb8 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sun, 20 Mar 2022 03:02:14 -0600 Subject: [PATCH 029/159] add recursive command line option --- freqtrade/commands/cli_options.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index f30c25ba1..955c1ae53 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -82,6 +82,11 @@ AVAILABLE_CLI_OPTIONS = { help='Reset sample files to their original state.', action='store_true', ), + "recursive": Arg( + '-r', '--recursive', + help='Recursively search for a strategy in the strategies folder.', + metavar='store_true', + ), # Main options "strategy": Arg( '-s', '--strategy', From f44ae494fb0c51510d27176d21cc17fd201b7234 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Thu, 31 Mar 2022 08:11:05 -0600 Subject: [PATCH 030/159] Added recursive to configuration --- freqtrade/configuration/configuration.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index 1ba17a04d..916c2b675 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -267,6 +267,12 @@ class Configuration: self._args_to_config(config, argname='strategy_list', logstring='Using strategy list of {} strategies', logfun=len) + self._args_to_config( + config, + argname='recursive', + logstring='Recursively searching for a strategy in the strategies folder.', + ) + self._args_to_config(config, argname='timeframe', logstring='Overriding timeframe with Command line argument') From b4b809ff8e19e3a0918cc8ff9e6ad1dbbb538077 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Thu, 31 Mar 2022 08:16:21 -0600 Subject: [PATCH 031/159] changed recursive to recursive_strategy_search --- freqtrade/commands/cli_options.py | 4 ++-- freqtrade/configuration/configuration.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index 955c1ae53..2ed42b299 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -82,8 +82,8 @@ AVAILABLE_CLI_OPTIONS = { help='Reset sample files to their original state.', action='store_true', ), - "recursive": Arg( - '-r', '--recursive', + "recursive_strategy_search": Arg( + '-r', '--recursive_strategy_search', help='Recursively search for a strategy in the strategies folder.', metavar='store_true', ), diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index 916c2b675..ae3ed45be 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -269,7 +269,7 @@ class Configuration: self._args_to_config( config, - argname='recursive', + argname='recursive_strategy_search', logstring='Recursively searching for a strategy in the strategies folder.', ) From 2fe5a1594f153b68bc576ebaaa0ceeb8397d5279 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Thu, 31 Mar 2022 08:16:41 -0600 Subject: [PATCH 032/159] Add conditional to recursive strategy searching if in config --- freqtrade/resolvers/strategy_resolver.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index 4f5d22e45..44f02e232 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -167,9 +167,13 @@ class StrategyResolver(IResolver): :param extra_dir: additional directory to search for the given strategy :return: Strategy instance or None """ - extra_dirs: List[str] = [ - path[0] for path in walk(f"{config['user_data_dir']}/{USERPATH_STRATEGIES}") - ] # sub-directories + if config['recursive_strategy_search']: + extra_dirs: List[str] = [ + path[0] for path in walk(f"{config['user_data_dir']}/{USERPATH_STRATEGIES}") + ] # sub-directories + else: + extra_dirs = [] + if extra_dir: extra_dirs.append(extra_dir) From 82e9f62381d4747dc87994349646b261e9a7a88d Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 5 Apr 2022 20:27:32 +0200 Subject: [PATCH 033/159] Add missing setting in arguments.py --- freqtrade/commands/arguments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 28f7d7148..2fb8d3258 100644 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -12,7 +12,7 @@ from freqtrade.constants import DEFAULT_CONFIG ARGS_COMMON = ["verbosity", "logfile", "version", "config", "datadir", "user_data_dir"] -ARGS_STRATEGY = ["strategy", "strategy_path"] +ARGS_STRATEGY = ["strategy", "strategy_path", "recursive_strategy_search"] ARGS_TRADE = ["db_url", "sd_notify", "dry_run", "dry_run_wallet", "fee"] From 1559692e4729115af3d63225a98e090e013d74c7 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Fri, 8 Apr 2022 11:44:42 +0100 Subject: [PATCH 034/159] Update hyperopt.py remove duplicates from list of asked points --- freqtrade/optimize/hyperopt.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 35f382469..2883199a9 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -422,16 +422,23 @@ class Hyperopt: 5. Repeat until at least `n_points` points in the `asked_non_tried` list 6. Return a list with length truncated at `n_points` ''' + def unique_list(a_list): + seen = [] + for x in a_list: + key = repr(x) + if key not in seen: + seen.append(eval(key)) + return seen i = 0 asked_non_tried: List[List[Any]] = [] is_random: List[bool] = [] while i < 5 and len(asked_non_tried) < n_points: if i < 3: self.opt.cache_ = {} - asked = self.opt.ask(n_points=n_points * 5) + asked = unique_list(self.opt.ask(n_points=n_points * 5)) is_random = [False for _ in range(len(asked))] else: - asked = self.opt.space.rvs(n_samples=n_points * 5) + asked = unique_list(self.opt.space.rvs(n_samples=n_points * 5)) is_random = [True for _ in range(len(asked))] asked_non_tried += [x for x in asked if x not in self.opt.Xi From d5ce868f1aa1d99c0f7d936cc88161611dc8aa4c Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sun, 10 Apr 2022 18:44:33 -0600 Subject: [PATCH 035/159] removed 1 letter alias for recursive-strategy-folder --- freqtrade/commands/cli_options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index 2ed42b299..095aad6c3 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -83,7 +83,7 @@ AVAILABLE_CLI_OPTIONS = { action='store_true', ), "recursive_strategy_search": Arg( - '-r', '--recursive_strategy_search', + '--recursive_strategy_search', help='Recursively search for a strategy in the strategies folder.', metavar='store_true', ), From c876d42e369baae4d86d7abd2db035454a6904b9 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sun, 10 Apr 2022 18:50:51 -0600 Subject: [PATCH 036/159] safe check for recursive_strategy_search in strategy_resolver --- freqtrade/resolvers/strategy_resolver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index 44f02e232..8a22dbd65 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -167,7 +167,7 @@ class StrategyResolver(IResolver): :param extra_dir: additional directory to search for the given strategy :return: Strategy instance or None """ - if config['recursive_strategy_search']: + if 'recursive_strategy_search' in config and config['recursive_strategy_search']: extra_dirs: List[str] = [ path[0] for path in walk(f"{config['user_data_dir']}/{USERPATH_STRATEGIES}") ] # sub-directories From 64e6729ae94b0c6027dc45be48b6185f7b1dbf6a Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sun, 10 Apr 2022 18:56:28 -0600 Subject: [PATCH 037/159] docs for recursive_strategy_search --- docs/configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configuration.md b/docs/configuration.md index 2cb5dfa93..9c1b3718c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -121,6 +121,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `order_types` | Configure order-types depending on the action (`"buy"`, `"sell"`, `"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 buy and sell 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 | `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 From d9039152ba8de5ca13af6ec7b85f5c17bfe9489d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Apr 2022 19:44:47 +0200 Subject: [PATCH 038/159] Add "get backtest historic results" endpoint --- freqtrade/data/btanalysis.py | 26 +++++++++++++++++++++++- freqtrade/rpc/api_server/api_backtest.py | 11 +++++++++- freqtrade/rpc/api_server/api_schemas.py | 7 +++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index db7ef66fc..4c178d8c8 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -160,6 +160,30 @@ def _load_and_merge_backtest_result(strategy_name: str, filename: Path, results: break +def _get_backtest_files(dirname: Path) -> List[Path]: + return reversed(sorted(dirname.glob('backtest-result-*-[0-9][0-9].json'))) + + +def get_backtest_resultlist(dirname: Path): + """ + Get list of backtest results read from metadata files + """ + results = [] + for filename in _get_backtest_files(dirname): + metadata = load_backtest_metadata(filename) + if not metadata: + continue + for s, v in metadata.items(): + results.append({ + 'filename': filename.name, + 'strategy': s, + 'run_id': v['run_id'], + 'backtest_start_time': v['backtest_start_time'], + + }) + return results + + def find_existing_backtest_stats(dirname: Union[Path, str], run_ids: Dict[str, str], min_backtest_date: datetime = None) -> Dict[str, Any]: """ @@ -179,7 +203,7 @@ def find_existing_backtest_stats(dirname: Union[Path, str], run_ids: Dict[str, s } # Weird glob expression here avoids including .meta.json files. - for filename in reversed(sorted(dirname.glob('backtest-result-*-[0-9][0-9].json'))): + for filename in _get_backtest_files(dirname): metadata = load_backtest_metadata(filename) if not metadata: # Files are sorted from newest to oldest. When file without metadata is encountered it diff --git a/freqtrade/rpc/api_server/api_backtest.py b/freqtrade/rpc/api_server/api_backtest.py index 757ed8aac..a44a98494 100644 --- a/freqtrade/rpc/api_server/api_backtest.py +++ b/freqtrade/rpc/api_server/api_backtest.py @@ -1,13 +1,16 @@ import asyncio import logging from copy import deepcopy +from typing import List from fastapi import APIRouter, BackgroundTasks, Depends from freqtrade.configuration.config_validation import validate_config_consistency +from freqtrade.data.btanalysis import get_backtest_resultlist from freqtrade.enums import BacktestState from freqtrade.exceptions import DependencyException -from freqtrade.rpc.api_server.api_schemas import BacktestRequest, BacktestResponse +from freqtrade.rpc.api_server.api_schemas import (BacktestHistoryEntry, BacktestRequest, + BacktestResponse) from freqtrade.rpc.api_server.deps import get_config, is_webserver_mode from freqtrade.rpc.api_server.webserver import ApiServer from freqtrade.rpc.rpc import RPCException @@ -200,3 +203,9 @@ def api_backtest_abort(ws_mode=Depends(is_webserver_mode)): "progress": 0, "status_msg": "Backtest ended", } + + +@router.get('/backtest/history', response_model=List[BacktestHistoryEntry], tags=['webserver', 'backtest']) +def api_backtest_history(config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): + # Get backtest result history, read from metadata files + return get_backtest_resultlist(config['user_data_dir'] / 'backtest_results') diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index ae797edad..a9135cce2 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -421,6 +421,13 @@ class BacktestResponse(BaseModel): backtest_result: Optional[Dict[str, Any]] +class BacktestHistoryEntry(BaseModel): + filename: str + strategy: str + run_id: str + backtest_start_time: int + + class SysInfo(BaseModel): cpu_pct: List[float] ram_pct: float From 85e7deb2cd60c235464b92dfdf4fd8ac630dcb41 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Apr 2022 20:04:47 +0200 Subject: [PATCH 039/159] Add loading of historic backtest result --- freqtrade/rpc/api_server/api_backtest.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/api_server/api_backtest.py b/freqtrade/rpc/api_server/api_backtest.py index a44a98494..9eeafd4d1 100644 --- a/freqtrade/rpc/api_server/api_backtest.py +++ b/freqtrade/rpc/api_server/api_backtest.py @@ -6,7 +6,7 @@ from typing import List from fastapi import APIRouter, BackgroundTasks, Depends from freqtrade.configuration.config_validation import validate_config_consistency -from freqtrade.data.btanalysis import get_backtest_resultlist +from freqtrade.data.btanalysis import get_backtest_resultlist, load_backtest_stats from freqtrade.enums import BacktestState from freqtrade.exceptions import DependencyException from freqtrade.rpc.api_server.api_schemas import (BacktestHistoryEntry, BacktestRequest, @@ -209,3 +209,17 @@ def api_backtest_abort(ws_mode=Depends(is_webserver_mode)): def api_backtest_history(config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): # Get backtest result history, read from metadata files return get_backtest_resultlist(config['user_data_dir'] / 'backtest_results') + + +@router.get('/backtest/history/result', response_model=BacktestResponse, tags=['webserver', 'backtest']) +def api_backtest_history_result(filename: str, config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): + # Get backtest result history, read from metadata files + fn = config['user_data_dir'] / 'backtest_results' / filename + return { + "status": "ended", + "running": False, + "step": "", + "progress": 1, + "status_msg": "Historic result", + "backtest_result": load_backtest_stats(fn) + } From 4254d8665861df31fe757f5b957d1194dd7562fb Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 Apr 2022 20:32:02 +0200 Subject: [PATCH 040/159] Move test-backtestfiles to separate directory --- tests/commands/test_commands.py | 2 +- tests/data/test_btanalysis.py | 27 ++++++++++--------- tests/optimize/test_optimize_reports.py | 10 +++---- tests/test_plotting.py | 8 +++--- .../{ => backtest_results}/.last_result.json | 0 .../backtest-result_multistrat.json | 0 .../backtest-result_new.json | 0 .../backtest-result_new.meta.json | 6 +++++ 8 files changed, 30 insertions(+), 23 deletions(-) rename tests/testdata/{ => backtest_results}/.last_result.json (100%) rename tests/testdata/{ => backtest_results}/backtest-result_multistrat.json (100%) rename tests/testdata/{ => backtest_results}/backtest-result_new.json (100%) create mode 100644 tests/testdata/backtest_results/backtest-result_new.meta.json diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 22869638b..1431bd22a 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -1429,7 +1429,7 @@ def test_backtesting_show(mocker, testdatadir, capsys): args = [ "backtesting-show", "--export-filename", - f"{testdatadir / 'backtest-result_new.json'}", + f"{testdatadir / 'backtest_results/backtest-result_new.json'}", "--show-pair-list" ] pargs = get_args(args) diff --git a/tests/data/test_btanalysis.py b/tests/data/test_btanalysis.py index f4275edd9..2b53e4900 100644 --- a/tests/data/test_btanalysis.py +++ b/tests/data/test_btanalysis.py @@ -27,18 +27,19 @@ def test_get_latest_backtest_filename(testdatadir, mocker): with pytest.raises(ValueError, match=r"Directory .* does not seem to contain .*"): - get_latest_backtest_filename(testdatadir.parent) + get_latest_backtest_filename(testdatadir) - res = get_latest_backtest_filename(testdatadir) + testdir_bt = testdatadir / "backtest_results" + res = get_latest_backtest_filename(testdir_bt) assert res == 'backtest-result_new.json' - res = get_latest_backtest_filename(str(testdatadir)) + res = get_latest_backtest_filename(str(testdir_bt)) assert res == 'backtest-result_new.json' mocker.patch("freqtrade.data.btanalysis.json_load", return_value={}) with pytest.raises(ValueError, match=r"Invalid '.last_result.json' format."): - get_latest_backtest_filename(testdatadir) + get_latest_backtest_filename(testdir_bt) def test_get_latest_hyperopt_file(testdatadir): @@ -81,7 +82,7 @@ def test_load_backtest_data_old_format(testdatadir, mocker): def test_load_backtest_data_new_format(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) assert isinstance(bt_data, DataFrame) assert set(bt_data.columns) == set(BT_DATA_COLUMNS + ['close_timestamp', 'open_timestamp']) @@ -92,19 +93,19 @@ def test_load_backtest_data_new_format(testdatadir): assert bt_data.equals(bt_data2) # Test loading from folder (must yield same result) - bt_data3 = load_backtest_data(testdatadir) + bt_data3 = load_backtest_data(testdatadir / "backtest_results") assert bt_data.equals(bt_data3) with pytest.raises(ValueError, match=r"File .* does not exist\."): load_backtest_data(str("filename") + "nofile") with pytest.raises(ValueError, match=r"Unknown dataformat."): - load_backtest_data(testdatadir / LAST_BT_RESULT_FN) + load_backtest_data(testdatadir / "backtest_results" / LAST_BT_RESULT_FN) def test_load_backtest_data_multi(testdatadir): - filename = testdatadir / "backtest-result_multistrat.json" + filename = testdatadir / "backtest_results/backtest-result_multistrat.json" for strategy in ('StrategyTestV2', 'TestStrategy'): bt_data = load_backtest_data(filename, strategy=strategy) assert isinstance(bt_data, DataFrame) @@ -182,7 +183,7 @@ def test_extract_trades_of_period(testdatadir): def test_analyze_trade_parallelism(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) res = analyze_trade_parallelism(bt_data, "5m") @@ -256,7 +257,7 @@ def test_combine_dataframes_with_mean_no_data(testdatadir): def test_create_cum_profit(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) timerange = TimeRange.parse_timerange("20180110-20180112") @@ -272,7 +273,7 @@ def test_create_cum_profit(testdatadir): def test_create_cum_profit1(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) # Move close-time to "off" the candle, to make sure the logic still works bt_data.loc[:, 'close_date'] = bt_data.loc[:, 'close_date'] + DateOffset(seconds=20) @@ -294,7 +295,7 @@ def test_create_cum_profit1(testdatadir): def test_calculate_max_drawdown(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) _, hdate, lowdate, hval, lval, drawdown = calculate_max_drawdown( bt_data, value_col="profit_abs") @@ -318,7 +319,7 @@ def test_calculate_max_drawdown(testdatadir): def test_calculate_csum(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) csum_min, csum_max = calculate_csum(bt_data) diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index d40fc1e2f..05c0bf575 100644 --- a/tests/optimize/test_optimize_reports.py +++ b/tests/optimize/test_optimize_reports.py @@ -228,7 +228,7 @@ def test_generate_pair_metrics(): def test_generate_daily_stats(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) res = generate_daily_stats(bt_data) assert isinstance(res, dict) @@ -248,7 +248,7 @@ def test_generate_daily_stats(testdatadir): def test_generate_trading_stats(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) res = generate_trading_stats(bt_data) assert isinstance(res, dict) @@ -332,7 +332,7 @@ def test_generate_sell_reason_stats(): def test_text_table_strategy(testdatadir): - filename = testdatadir / "backtest-result_multistrat.json" + filename = testdatadir / "backtest_results/backtest-result_multistrat.json" bt_res_data = load_backtest_stats(filename) bt_res_data_comparison = bt_res_data.pop('strategy_comparison') @@ -364,7 +364,7 @@ def test_generate_edge_table(): def test_generate_periodic_breakdown_stats(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename).to_dict(orient='records') res = generate_periodic_breakdown_stats(bt_data, 'day') @@ -392,7 +392,7 @@ def test__get_resample_from_period(): def test_show_sorted_pairlist(testdatadir, default_conf, capsys): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_stats(filename) default_conf['backtest_show_pair_list'] = True diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 940639465..97f367608 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -157,7 +157,7 @@ def test_plot_trades(testdatadir, caplog): assert fig == fig1 assert log_has("No trades found.", caplog) pair = "ADA/BTC" - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" trades = load_backtest_data(filename) trades = trades.loc[trades['pair'] == pair] @@ -298,7 +298,7 @@ def test_generate_plot_file(mocker, caplog): def test_add_profit(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" bt_data = load_backtest_data(filename) timerange = TimeRange.parse_timerange("20180110-20180112") @@ -318,7 +318,7 @@ def test_add_profit(testdatadir): def test_generate_profit_graph(testdatadir): - filename = testdatadir / "backtest-result_new.json" + filename = testdatadir / "backtest_results/backtest-result_new.json" trades = load_backtest_data(filename) timerange = TimeRange.parse_timerange("20180110-20180112") pairs = ["TRX/BTC", "XLM/BTC"] @@ -456,7 +456,7 @@ def test_plot_profit(default_conf, mocker, testdatadir): match=r"No trades found, cannot generate Profit-plot.*"): plot_profit(default_conf) - default_conf['exportfilename'] = testdatadir / "backtest-result_new.json" + default_conf['exportfilename'] = testdatadir / "backtest_results/backtest-result_new.json" plot_profit(default_conf) diff --git a/tests/testdata/.last_result.json b/tests/testdata/backtest_results/.last_result.json similarity index 100% rename from tests/testdata/.last_result.json rename to tests/testdata/backtest_results/.last_result.json diff --git a/tests/testdata/backtest-result_multistrat.json b/tests/testdata/backtest_results/backtest-result_multistrat.json similarity index 100% rename from tests/testdata/backtest-result_multistrat.json rename to tests/testdata/backtest_results/backtest-result_multistrat.json diff --git a/tests/testdata/backtest-result_new.json b/tests/testdata/backtest_results/backtest-result_new.json similarity index 100% rename from tests/testdata/backtest-result_new.json rename to tests/testdata/backtest_results/backtest-result_new.json diff --git a/tests/testdata/backtest_results/backtest-result_new.meta.json b/tests/testdata/backtest_results/backtest-result_new.meta.json new file mode 100644 index 000000000..57ecdb19d --- /dev/null +++ b/tests/testdata/backtest_results/backtest-result_new.meta.json @@ -0,0 +1,6 @@ +{ + "StrategyTestV3": { + "run_id": "430d0271075ef327edbb23088f4db4ebe51a3dbf", + "backtest_start_time": 1648904006 + } +} From 0c87702545c587525054b90bd6ca2c0f8298e7af Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 12 Apr 2022 06:28:37 +0200 Subject: [PATCH 041/159] test for backtest history --- tests/rpc/test_rpc_apiserver.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 54bf07dc2..ee54e95dd 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1581,6 +1581,34 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir): assert result['status_msg'] == 'Backtest reset' +def test_api_backtest_history(botclient, mocker, testdatadir): + ftbot, client = botclient + mocker.patch('freqtrade.data.btanalysis._get_backtest_files', + return_value=[ + testdatadir / 'backtest_results/backtest-result_multistrat.json', + testdatadir / 'backtest_results/backtest-result_new.json' + ]) + + rc = client_get(client, f"{BASE_URI}/backtest/history") + assert_response(rc, 502) + ftbot.config['user_data_dir'] = testdatadir + ftbot.config['runmode'] = RunMode.WEBSERVER + + rc = client_get(client, f"{BASE_URI}/backtest/history") + assert_response(rc) + result = rc.json() + assert len(result) == 1 + fn = result[0]['filename'] + rc = client_get(client, f"{BASE_URI}/backtest/history/result?filename={fn}") + assert_response(rc) + result2 = rc.json() + assert result2 + assert result2['status'] == 'ended' + assert not result2['running'] + assert result2['progress'] == 1 + assert result2['backtest_result']['strategy'][CURRENT_TEST_STRATEGY] + + def test_health(botclient): ftbot, client = botclient From dd5693f4e5ed238513fd8b45916eaa1f6a952ee2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 12 Apr 2022 07:21:20 +0200 Subject: [PATCH 042/159] Add note about binance Futures trading rules closes #6683 --- docs/exchanges.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/exchanges.md b/docs/exchanges.md index b808096d2..18a7af5a1 100644 --- a/docs/exchanges.md +++ b/docs/exchanges.md @@ -64,7 +64,10 @@ Binance supports [time_in_force](configuration.md#understand-order_time_in_force For Binance, please add `"BNB/"` to your blacklist to avoid issues. Accounts having BNB accounts use this to pay for fees - if your first trade happens to be on `BNB`, further trades will consume this position and make the initial BNB trade unsellable as the expected amount is not there anymore. -### Binance Futures' order pricing +### Binance Futures + +Binance has specific (unfortunately complex) [Futures Trading Quantitative Rules](https://www.binance.com/en/support/faq/4f462ebe6ff445d4a170be7d9e897272) which need to be followed, and which prohibit a too low stake-amount (among others) for too many orders. +Violating these rules will result in a trading restriction. When trading on Binance Futures market, orderbook must be used because there is no price ticker data for futures. From fa298d6f1c1b4fd57161b14ae16259a759daa84f Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Tue, 12 Apr 2022 23:57:40 +0100 Subject: [PATCH 043/159] fix unique_list logic --- freqtrade/optimize/hyperopt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 748cc0806..0d71e4ff5 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -426,8 +426,8 @@ class Hyperopt: for x in a_list: key = repr(x) if key not in seen: - seen.append(eval(key)) - return seen + seen.append(key) + return [eval(x) for x in seen] i = 0 asked_non_tried: List[List[Any]] = [] is_random: List[bool] = [] From 4ac54a76af7f61815a7635768c66e1c42f70930d Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 13 Apr 2022 06:47:39 +0200 Subject: [PATCH 044/159] Add strategy as mandatory argument --- freqtrade/data/btanalysis.py | 11 +++++++++-- freqtrade/rpc/api_server/api_backtest.py | 13 ++++++++++--- tests/rpc/test_rpc_apiserver.py | 3 ++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index 4c178d8c8..ffa7fe0c0 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -149,7 +149,14 @@ def load_backtest_stats(filename: Union[Path, str]) -> Dict[str, Any]: return data -def _load_and_merge_backtest_result(strategy_name: str, filename: Path, results: Dict[str, Any]): +def load_and_merge_backtest_result(strategy_name: str, filename: Path, results: Dict[str, Any]): + """ + Load one strategy from multi-strategy result + and merge it with results + :param strategy_name: Name of the strategy contained in the result + :param filename: Backtest-result-filename to load + :param results: dict to merge the result to. + """ bt_data = load_backtest_stats(filename) for k in ('metadata', 'strategy'): results[k][strategy_name] = bt_data[k][strategy_name] @@ -226,7 +233,7 @@ def find_existing_backtest_stats(dirname: Union[Path, str], run_ids: Dict[str, s if strategy_metadata['run_id'] == run_id: del run_ids[strategy_name] - _load_and_merge_backtest_result(strategy_name, filename, results) + load_and_merge_backtest_result(strategy_name, filename, results) if len(run_ids) == 0: break diff --git a/freqtrade/rpc/api_server/api_backtest.py b/freqtrade/rpc/api_server/api_backtest.py index 9eeafd4d1..b11b28685 100644 --- a/freqtrade/rpc/api_server/api_backtest.py +++ b/freqtrade/rpc/api_server/api_backtest.py @@ -6,7 +6,7 @@ from typing import List from fastapi import APIRouter, BackgroundTasks, Depends from freqtrade.configuration.config_validation import validate_config_consistency -from freqtrade.data.btanalysis import get_backtest_resultlist, load_backtest_stats +from freqtrade.data.btanalysis import get_backtest_resultlist, load_and_merge_backtest_result from freqtrade.enums import BacktestState from freqtrade.exceptions import DependencyException from freqtrade.rpc.api_server.api_schemas import (BacktestHistoryEntry, BacktestRequest, @@ -212,14 +212,21 @@ def api_backtest_history(config=Depends(get_config), ws_mode=Depends(is_webserve @router.get('/backtest/history/result', response_model=BacktestResponse, tags=['webserver', 'backtest']) -def api_backtest_history_result(filename: str, config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): +def api_backtest_history_result(filename: str, strategy: str, config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): # Get backtest result history, read from metadata files fn = config['user_data_dir'] / 'backtest_results' / filename + results = { + 'metadata': {}, + 'strategy': {}, + 'strategy_comparison': [], + } + + load_and_merge_backtest_result(strategy, fn, results) return { "status": "ended", "running": False, "step": "", "progress": 1, "status_msg": "Historic result", - "backtest_result": load_backtest_stats(fn) + "backtest_result": results, } diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index ee54e95dd..52ab35c36 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1599,7 +1599,8 @@ def test_api_backtest_history(botclient, mocker, testdatadir): result = rc.json() assert len(result) == 1 fn = result[0]['filename'] - rc = client_get(client, f"{BASE_URI}/backtest/history/result?filename={fn}") + strategy = result[0]['strategy'] + rc = client_get(client, f"{BASE_URI}/backtest/history/result?filename={fn}&strategy={strategy}") assert_response(rc) result2 = rc.json() assert result2 From f89b64c972a5bb7b45b5fc99a0b0b33a510445ac Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 13 Apr 2022 06:55:47 +0200 Subject: [PATCH 045/159] Improve test by having multistrat.meta file available --- freqtrade/data/btanalysis.py | 2 +- freqtrade/rpc/api_server/api_backtest.py | 4 ++-- freqtrade/rpc/api_server/api_v1.py | 3 ++- tests/rpc/test_rpc_apiserver.py | 7 +++++-- .../backtest-result_multistrat.meta.json | 10 ++++++++++ 5 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 tests/testdata/backtest_results/backtest-result_multistrat.meta.json diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index ffa7fe0c0..8abcc6747 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -168,7 +168,7 @@ def load_and_merge_backtest_result(strategy_name: str, filename: Path, results: def _get_backtest_files(dirname: Path) -> List[Path]: - return reversed(sorted(dirname.glob('backtest-result-*-[0-9][0-9].json'))) + return list(reversed(sorted(dirname.glob('backtest-result-*-[0-9][0-9].json')))) def get_backtest_resultlist(dirname: Path): diff --git a/freqtrade/rpc/api_server/api_backtest.py b/freqtrade/rpc/api_server/api_backtest.py index b11b28685..a902ea984 100644 --- a/freqtrade/rpc/api_server/api_backtest.py +++ b/freqtrade/rpc/api_server/api_backtest.py @@ -1,7 +1,7 @@ import asyncio import logging from copy import deepcopy -from typing import List +from typing import Any, Dict, List from fastapi import APIRouter, BackgroundTasks, Depends @@ -215,7 +215,7 @@ def api_backtest_history(config=Depends(get_config), ws_mode=Depends(is_webserve def api_backtest_history_result(filename: str, strategy: str, config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): # Get backtest result history, read from metadata files fn = config['user_data_dir'] / 'backtest_results' / filename - results = { + results: Dict[str, Any] = { 'metadata': {}, 'strategy': {}, 'strategy_comparison': [], diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index d96154824..5021c99f9 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -35,7 +35,8 @@ logger = logging.getLogger(__name__) # 1.13: forcebuy supports stake_amount # versions 2.xx -> futures/short branch # 2.14: Add entry/exit orders to trade response -API_VERSION = 2.14 +# 2.15: Add backtest history endpoints +API_VERSION = 2.15 # Public API, requires no auth. router_public = APIRouter() diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 52ab35c36..af8361571 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1597,8 +1597,9 @@ def test_api_backtest_history(botclient, mocker, testdatadir): rc = client_get(client, f"{BASE_URI}/backtest/history") assert_response(rc) result = rc.json() - assert len(result) == 1 + assert len(result) == 3 fn = result[0]['filename'] + assert fn == "backtest-result_multistrat.json" strategy = result[0]['strategy'] rc = client_get(client, f"{BASE_URI}/backtest/history/result?filename={fn}&strategy={strategy}") assert_response(rc) @@ -1607,7 +1608,9 @@ def test_api_backtest_history(botclient, mocker, testdatadir): assert result2['status'] == 'ended' assert not result2['running'] assert result2['progress'] == 1 - assert result2['backtest_result']['strategy'][CURRENT_TEST_STRATEGY] + # Only one strategy loaded - even though we use multiresult + assert len(result2['backtest_result']['strategy']) == 1 + assert result2['backtest_result']['strategy'][strategy] def test_health(botclient): diff --git a/tests/testdata/backtest_results/backtest-result_multistrat.meta.json b/tests/testdata/backtest_results/backtest-result_multistrat.meta.json new file mode 100644 index 000000000..906edcece --- /dev/null +++ b/tests/testdata/backtest_results/backtest-result_multistrat.meta.json @@ -0,0 +1,10 @@ +{ + "StrategyTestV2": { + "run_id": "430d0271075ef327edbb23088f4db4ebe51a3dbf", + "backtest_start_time": 1648904006 + }, + "TestStrategy": { + "run_id": "110d0271075ef327edbb23085102b4ebe51a3d55", + "backtest_start_time": 1648904006 + } +} From 35cea6dcfa5a816cc223a966f72a1764a7c0fb93 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Wed, 13 Apr 2022 09:36:46 +0100 Subject: [PATCH 046/159] fix unique_list --- freqtrade/optimize/hyperopt.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 0d71e4ff5..24d2b910d 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -422,12 +422,11 @@ class Hyperopt: 6. Return a list with length truncated at `n_points` ''' def unique_list(a_list): - seen = [] - for x in a_list: - key = repr(x) - if key not in seen: - seen.append(key) - return [eval(x) for x in seen] + new_list = [] + for item in a_list: + if item not in new_list: + new_list.append(item) + return new_list i = 0 asked_non_tried: List[List[Any]] = [] is_random: List[bool] = [] From b1a6db8d29dadf33ea9349ffa324c87d91ebc5b1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 13 Apr 2022 19:24:21 +0200 Subject: [PATCH 047/159] Fix bad usage of base_currency --- freqtrade/rpc/telegram.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 5699b58aa..c2531fec3 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -387,7 +387,7 @@ class Telegram(RPCHandler): else: return "\N{CROSS MARK}" - def _prepare_entry_details(self, filled_orders: List, base_currency: str, is_open: bool): + def _prepare_entry_details(self, filled_orders: List, quote_currency: str, is_open: bool): """ Prepare details of trade with entry adjustment enabled """ @@ -405,7 +405,7 @@ class Telegram(RPCHandler): if x == 0: lines.append(f"*Entry #{x+1}:*") lines.append( - f"*Entry Amount:* {cur_entry_amount} ({order['cost']:.8f} {base_currency})") + f"*Entry Amount:* {cur_entry_amount} ({order['cost']:.8f} {quote_currency})") lines.append(f"*Average Entry Price:* {cur_entry_average}") else: sumA = 0 @@ -429,7 +429,7 @@ class Telegram(RPCHandler): lines.append("({})".format(cur_entry_datetime .humanize(granularity=["day", "hour", "minute"]))) lines.append( - f"*Entry Amount:* {cur_entry_amount} ({order['cost']:.8f} {base_currency})") + f"*Entry Amount:* {cur_entry_amount} ({order['cost']:.8f} {quote_currency})") lines.append(f"*Average Entry Price:* {cur_entry_average} " f"({price_to_1st_entry:.2%} from 1st entry rate)") lines.append(f"*Order filled at:* {order['order_filled_date']}") @@ -472,7 +472,7 @@ class Telegram(RPCHandler): "*Current Pair:* {pair}", "*Direction:* " + ("`Short`" if r.get('is_short') else "`Long`"), "*Leverage:* `{leverage}`" if r.get('leverage') else "", - "*Amount:* `{amount} ({stake_amount} {base_currency})`", + "*Amount:* `{amount} ({stake_amount} {quote_currency})`", "*Enter Tag:* `{enter_tag}`" if r['enter_tag'] else "", "*Exit Reason:* `{exit_reason}`" if r['exit_reason'] else "", ] From 4acb77305a78940b64f1ee5550130da503dc0ced Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 13 Apr 2022 19:33:27 +0200 Subject: [PATCH 048/159] Don't break when running hyperopt-x tools on old resuts --- freqtrade/optimize/hyperopt_tools.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index 83df7e83c..1610b3b5b 100755 --- a/freqtrade/optimize/hyperopt_tools.py +++ b/freqtrade/optimize/hyperopt_tools.py @@ -310,12 +310,15 @@ class HyperoptTools(): if not has_drawdown: # Ensure compatibility with older versions of hyperopt results trials['results_metrics.max_drawdown_account'] = None + if 'is_random' not in trials.columns: + trials['is_random'] = False # New mode, using backtest result for metrics trials['results_metrics.winsdrawslosses'] = trials.apply( lambda x: f"{x['results_metrics.wins']} {x['results_metrics.draws']:>4} " f"{x['results_metrics.losses']:>4}", axis=1) + trials = trials[['Best', 'current_epoch', 'results_metrics.total_trades', 'results_metrics.winsdrawslosses', 'results_metrics.profit_mean', 'results_metrics.profit_total_abs', From 340c0ea391f4ac89b01352ff6d4fd947715a694b Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Thu, 14 Apr 2022 14:15:11 +0100 Subject: [PATCH 049/159] update is_random before asked_non_tried is_random depends on asked_non_tried and needs to be updated first --- freqtrade/optimize/hyperopt.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 24d2b910d..babcc5491 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -438,12 +438,12 @@ class Hyperopt: else: asked = unique_list(self.opt.space.rvs(n_samples=n_points * 5)) is_random = [True for _ in range(len(asked))] - asked_non_tried += [x for x in asked - if x not in self.opt.Xi - and x not in asked_non_tried] is_random += [rand for x, rand in zip(asked, is_random) if x not in self.opt.Xi and x not in asked_non_tried] + asked_non_tried += [x for x in asked + if x not in self.opt.Xi + and x not in asked_non_tried] i += 1 if asked_non_tried: From 1153e65b3ecbb8ec97656a631890c66cf46af165 Mon Sep 17 00:00:00 2001 From: Italo <45588475+italodamato@users.noreply.github.com> Date: Thu, 14 Apr 2022 14:34:04 +0100 Subject: [PATCH 050/159] fix flake8 --- freqtrade/optimize/hyperopt_tools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index 1610b3b5b..32a095ad8 100755 --- a/freqtrade/optimize/hyperopt_tools.py +++ b/freqtrade/optimize/hyperopt_tools.py @@ -318,7 +318,6 @@ class HyperoptTools(): lambda x: f"{x['results_metrics.wins']} {x['results_metrics.draws']:>4} " f"{x['results_metrics.losses']:>4}", axis=1) - trials = trials[['Best', 'current_epoch', 'results_metrics.total_trades', 'results_metrics.winsdrawslosses', 'results_metrics.profit_mean', 'results_metrics.profit_total_abs', From d23d8303465252aff20d46a0ce85b710669ade50 Mon Sep 17 00:00:00 2001 From: kokimame Date: Fri, 15 Apr 2022 00:35:11 +0900 Subject: [PATCH 051/159] Avoid ignoring the case precision amount = 0 --- 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 af3e4c3eb..e0da0878d 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -651,7 +651,7 @@ class Exchange: Re-implementation of ccxt internal methods - ensuring we can test the result is correct based on our definitions. """ - if self.markets[pair]['precision']['amount']: + if self.markets[pair]['precision']['amount'] is not None: amount = float(decimal_to_precision(amount, rounding_mode=TRUNCATE, precision=self.markets[pair]['precision']['amount'], counting_mode=self.precisionMode, From f61d4d36c337f618086c5e4084d1e9cde5ed9718 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 15 Apr 2022 14:48:09 +0200 Subject: [PATCH 052/159] Add test for 0 precision amount --- tests/exchange/test_exchange.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index cffeec5b3..e99121489 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -231,6 +231,10 @@ def test_validate_order_time_in_force(default_conf, mocker, caplog): (2.34559, 2, 3, 1, 2.345, 'spot'), (2.9999, 2, 3, 1, 2.999, 'spot'), (2.9909, 2, 3, 1, 2.990, 'spot'), + (2.9909, 2, 0, 1, 2, 'spot'), + (29991.5555, 2, 0, 1, 29991, 'spot'), + (29991.5555, 2, -1, 1, 29990, 'spot'), + (29991.5555, 2, -2, 1, 29900, 'spot'), # Tests for Tick-size (2.34559, 4, 0.0001, 1, 2.3455, 'spot'), (2.34559, 4, 0.00001, 1, 2.34559, 'spot'), From 4019c05feeac51680b2c2c8e315b0851bccd63c3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 16 Apr 2022 06:47:56 +0200 Subject: [PATCH 053/159] Update entry/exit timeout documentation the type of order is now an Order, no longer a dictionary. closes #6691 --- docs/strategy-callbacks.md | 16 ++++++------ docs/strategy_migration.md | 4 +-- freqtrade/strategy/interface.py | 26 +++++++++---------- .../subtemplates/strategy_methods_advanced.j2 | 18 ++++++++----- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index bd32f41c3..7ec600a58 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -418,7 +418,7 @@ The function must return either `True` (cancel order) or `False` (keep order ali ``` python from datetime import datetime, timedelta -from freqtrade.persistence import Trade +from freqtrade.persistence import Trade, Order class AwesomeStrategy(IStrategy): @@ -430,7 +430,7 @@ class AwesomeStrategy(IStrategy): 'exit': 60 * 25 } - def check_entry_timeout(self, pair: str, trade: 'Trade', order: dict, + def check_entry_timeout(self, pair: str, trade: 'Trade', order: 'Order', current_time: datetime, **kwargs) -> bool: if trade.open_rate > 100 and trade.open_date_utc < current_time - timedelta(minutes=5): return True @@ -441,7 +441,7 @@ class AwesomeStrategy(IStrategy): return False - def check_exit_timeout(self, pair: str, trade: Trade, order: dict, + def check_exit_timeout(self, pair: str, trade: Trade, order: 'Order', current_time: datetime, **kwargs) -> bool: if trade.open_rate > 100 and trade.open_date_utc < current_time - timedelta(minutes=5): return True @@ -459,7 +459,7 @@ class AwesomeStrategy(IStrategy): ``` python from datetime import datetime -from freqtrade.persistence import Trade +from freqtrade.persistence import Trade, Order class AwesomeStrategy(IStrategy): @@ -471,22 +471,22 @@ class AwesomeStrategy(IStrategy): 'exit': 60 * 25 } - def check_entry_timeout(self, pair: str, trade: Trade, order: dict, + def check_entry_timeout(self, pair: str, trade: 'Trade', order: 'Order', current_time: datetime, **kwargs) -> bool: ob = self.dp.orderbook(pair, 1) current_price = ob['bids'][0][0] # Cancel buy order if price is more than 2% above the order. - if current_price > order['price'] * 1.02: + if current_price > order.price * 1.02: return True return False - def check_exit_timeout(self, pair: str, trade: Trade, order: dict, + def check_exit_timeout(self, pair: str, trade: 'Trade', order: 'Order', current_time: datetime, **kwargs) -> bool: ob = self.dp.orderbook(pair, 1) current_price = ob['asks'][0][0] # Cancel sell order if price is more than 2% below the order. - if current_price < order['price'] * 0.98: + if current_price < order.price * 0.98: return True return False ``` diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index ac8d3e489..458e80d0e 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -183,11 +183,11 @@ class AwesomeStrategy(IStrategy): ``` python hl_lines="2 6" class AwesomeStrategy(IStrategy): - def check_entry_timeout(self, pair: str, trade: 'Trade', order: dict, + def check_entry_timeout(self, pair: str, trade: 'Trade', order: 'Order', current_time: datetime, **kwargs) -> bool: return False - def check_exit_timeout(self, pair: str, trade: 'Trade', order: dict, + def check_exit_timeout(self, pair: str, trade: 'Trade', order: 'Order', current_time: datetime, **kwargs) -> bool: return False ``` diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index ba2eb9636..afcc1aa99 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -206,18 +206,18 @@ class IStrategy(ABC, HyperStrategyMixin): """ pass - def check_buy_timeout(self, pair: str, trade: Trade, order: dict, + def check_buy_timeout(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> bool: """ DEPRECATED: Please use `check_entry_timeout` instead. """ return False - def check_entry_timeout(self, pair: str, trade: Trade, order: dict, + def check_entry_timeout(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> bool: """ Check entry timeout function callback. - This method can be used to override the enter-timeout. + This method can be used to override the entry-timeout. It is called whenever a limit entry order has been created, and is not yet fully filled. Configuration options in `unfilledtimeout` will be verified before this, @@ -225,8 +225,8 @@ class IStrategy(ABC, HyperStrategyMixin): When not implemented by a strategy, this simply returns False. :param pair: Pair the trade is for - :param trade: trade object. - :param order: Order dictionary as returned from CCXT. + :param trade: Trade object. + :param order: Order object. :param current_time: datetime object, containing the current datetime :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return bool: When True is returned, then the entry order is cancelled. @@ -234,30 +234,30 @@ class IStrategy(ABC, HyperStrategyMixin): return self.check_buy_timeout( pair=pair, trade=trade, order=order, current_time=current_time) - def check_sell_timeout(self, pair: str, trade: Trade, order: dict, + def check_sell_timeout(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> bool: """ DEPRECATED: Please use `check_exit_timeout` instead. """ return False - def check_exit_timeout(self, pair: str, trade: Trade, order: dict, + def check_exit_timeout(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> bool: """ - Check sell timeout function callback. + Check exit timeout function callback. This method can be used to override the exit-timeout. - It is called whenever a (long) limit sell order or (short) limit buy - has been created, and is not yet fully filled. + It is called whenever a limit exit order has been created, + and is not yet fully filled. Configuration options in `unfilledtimeout` will be verified before this, so ensure to set these timeouts high enough. When not implemented by a strategy, this simply returns False. :param pair: Pair the trade is for - :param trade: trade object. - :param order: Order dictionary as returned from CCXT. + :param trade: Trade object. + :param order: Order object :param current_time: datetime object, containing the current datetime :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - :return bool: When True is returned, then the (long)sell/(short)buy-order is cancelled. + :return bool: When True is returned, then the exit-order is cancelled. """ return self.check_sell_timeout( pair=pair, trade=trade, order=order, current_time=current_time) diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index 17dfa0873..d5e2ea8ce 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -170,7 +170,8 @@ def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: """ return True -def check_entry_timeout(self, pair: str, trade: 'Trade', order: dict, **kwargs) -> bool: +def check_entry_timeout(self, pair: str, trade: 'Trade', order: 'Order', + current_time: datetime, **kwargs) -> bool: """ Check entry timeout function callback. This method can be used to override the entry-timeout. @@ -183,14 +184,16 @@ def check_entry_timeout(self, pair: str, trade: 'Trade', order: dict, **kwargs) When not implemented by a strategy, this simply returns False. :param pair: Pair the trade is for - :param trade: trade object. - :param order: Order dictionary as returned from CCXT. + :param trade: Trade object. + :param order: Order object. + :param current_time: datetime object, containing the current datetime :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - :return bool: When True is returned, then the buy-order is cancelled. + :return bool: When True is returned, then the entry order is cancelled. """ return False -def check_exit_timeout(self, pair: str, trade: 'Trade', order: dict, **kwargs) -> bool: +def check_exit_timeout(self, pair: str, trade: 'Trade', order: 'Order', + current_time: datetime, **kwargs) -> bool: """ Check exit timeout function callback. This method can be used to override the exit-timeout. @@ -203,8 +206,9 @@ def check_exit_timeout(self, pair: str, trade: 'Trade', order: dict, **kwargs) - When not implemented by a strategy, this simply returns False. :param pair: Pair the trade is for - :param trade: trade object. - :param order: Order dictionary as returned from CCXT. + :param trade: Trade object. + :param order: Order object. + :param current_time: datetime object, containing the current datetime :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return bool: When True is returned, then the exit-order is cancelled. """ From 26ba899d7d565581763d7509e5a041ad4bcb7160 Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 14:37:36 +0100 Subject: [PATCH 054/159] Add constant, boolean check, rename option to fit with other x_enable, check that RunMode is BACKTEST --- freqtrade/constants.py | 1 + freqtrade/optimize/backtesting.py | 10 ++++------ freqtrade/optimize/optimize_reports.py | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/freqtrade/constants.py b/freqtrade/constants.py index c6a2ab5d3..d21020a3f 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -380,6 +380,7 @@ CONF_SCHEMA = { }, 'position_adjustment_enable': {'type': 'boolean'}, 'max_entry_position_adjustment': {'type': ['integer', 'number'], 'minimum': -1}, + 'backtest_signal_candle_export_enable': {'type': 'boolean'}, }, 'definitions': { 'exchange': { diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 11704a70b..b8f63d006 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -19,7 +19,7 @@ from freqtrade.data import history from freqtrade.data.btanalysis import find_existing_backtest_stats, trade_list_to_dataframe from freqtrade.data.converter import trim_dataframe, trim_dataframes from freqtrade.data.dataprovider import DataProvider -from freqtrade.enums import BacktestState, CandleType, ExitCheckTuple, ExitType, TradingMode +from freqtrade.enums import BacktestState, CandleType, ExitCheckTuple, ExitType, TradingMode, RunMode from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.misc import get_strategy_run_id @@ -74,7 +74,7 @@ class Backtesting: self.strategylist: List[IStrategy] = [] self.all_results: Dict[str, Dict] = {} self.processed_dfs: Dict[str, Dict] = {} - + self._exchange_name = self.config['exchange']['name'] self.exchange = ExchangeResolver.load_exchange(self._exchange_name, self.config) self.dataprovider = DataProvider(self.config, self.exchange) @@ -129,9 +129,7 @@ class Backtesting: self.config['startup_candle_count'] = self.required_startup self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe) - self.enable_backtest_signal_candle_export = False - if self.config.get('enable_backtest_signal_candle_export', None) is not None: - self.enable_backtest_signal_candle_export = bool(self.config.get('enable_backtest_signal_candle_export')) + self.backtest_signal_candle_export_enable = self.config.get('backtest_signal_candle_export_enable', False) self.trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT) # strategies which define "can_short=True" will fail to load in Spot mode. @@ -1076,7 +1074,7 @@ class Backtesting: }) self.all_results[self.strategy.get_strategy_name()] = results - if self.enable_backtest_signal_candle_export: + if self.backtest_signal_candle_export_enable and self.dataprovider.runmode == RunMode.BACKTEST: signal_candles_only = {} for pair in preprocessed_tmp.keys(): signal_candles_only_df = DataFrame() diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index c08fa07a1..a97a6cf0f 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -44,6 +44,25 @@ def store_backtest_stats(recordfilename: Path, stats: Dict[str, DataFrame]) -> N latest_filename = Path.joinpath(filename.parent, LAST_BT_RESULT_FN) file_dump_json(latest_filename, {'latest_backtest': str(filename.name)}) +def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict]) -> None: + """ + Stores backtest trade signal candles + :param recordfilename: Path object, which can either be a filename or a directory. + Filenames will be appended with a timestamp right before the suffix + while for directories, /backtest-result-_signals.pkl will be used as filename + :param stats: Dict containing the backtesting signal candles + """ + if recordfilename.is_dir(): + filename = (recordfilename / + f'backtest-result-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}_signals.pkl') + else: + filename = Path.joinpath( + recordfilename.parent, + f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}' + ).with_suffix(recordfilename.suffix) + + with open(filename, 'wb') as f: + pickle.dump(candles, f) def _get_line_floatfmt(stake_currency: str) -> List[str]: """ From 21734c5de77697cb75a5ebee8e52b1b9bce6b10a Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 14:46:30 +0100 Subject: [PATCH 055/159] Add pickle import --- freqtrade/optimize/backtesting.py | 1 + freqtrade/optimize/optimize_reports.py | 1 + 2 files changed, 2 insertions(+) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index b8f63d006..cc7dbb1fb 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -8,6 +8,7 @@ from collections import defaultdict from copy import deepcopy from datetime import datetime, timedelta, timezone from typing import Any, Dict, List, Optional, Tuple +import pickle from numpy import nan from pandas import DataFrame diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index a97a6cf0f..4265ca70d 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -3,6 +3,7 @@ from copy import deepcopy from datetime import datetime, timedelta, timezone from pathlib import Path from typing import Any, Dict, List, Union +import pickle from numpy import int64 from pandas import DataFrame, to_datetime From 8990ba27099357c7f63540fd05e7c7db98961270 Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 14:49:53 +0100 Subject: [PATCH 056/159] Fix store signal candles --- freqtrade/optimize/backtesting.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index cc7dbb1fb..4ed3f85be 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -27,7 +27,7 @@ from freqtrade.misc import get_strategy_run_id from freqtrade.mixins import LoggingMixin from freqtrade.optimize.bt_progress import BTProgress from freqtrade.optimize.optimize_reports import (generate_backtest_stats, show_backtest_results, - store_backtest_stats) + store_backtest_stats, store_backtest_signal_candles) from freqtrade.persistence import LocalTrade, Order, PairLocks, Trade from freqtrade.plugins.pairlistmanager import PairListManager from freqtrade.plugins.protectionmanager import ProtectionManager @@ -1157,6 +1157,9 @@ class Backtesting: if self.config.get('export', 'none') == 'trades': store_backtest_stats(self.config['exportfilename'], self.results) + if self.enable_backtest_signal_candle_export and self.dataprovider.runmode == RunMode.BACKTEST: + store_backtest_signal_candles(self.config['exportfilename'], self.processed_dfs) + # Results may be mixed up now. Sort them so they follow --strategy-list order. if 'strategy_list' in self.config and len(self.results) > 0: self.results['strategy_comparison'] = sorted( From b1bcf9f33c8157fc1e62fa67532151afaaacb8f2 Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 14:58:17 +0100 Subject: [PATCH 057/159] Fix backtest_enable typo --- freqtrade/optimize/backtesting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 4ed3f85be..f19cd488e 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -1157,7 +1157,7 @@ class Backtesting: if self.config.get('export', 'none') == 'trades': store_backtest_stats(self.config['exportfilename'], self.results) - if self.enable_backtest_signal_candle_export and self.dataprovider.runmode == RunMode.BACKTEST: + if self.backtest_signal_candle_export_enable and self.dataprovider.runmode == RunMode.BACKTEST: store_backtest_signal_candles(self.config['exportfilename'], self.processed_dfs) # Results may be mixed up now. Sort them so they follow --strategy-list order. From f55a9940a7e812f07437e4a207652b8152d7d131 Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 16:15:04 +0100 Subject: [PATCH 058/159] Fix line spacing --- freqtrade/optimize/optimize_reports.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 4265ca70d..f870bd1f5 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -45,6 +45,7 @@ def store_backtest_stats(recordfilename: Path, stats: Dict[str, DataFrame]) -> N latest_filename = Path.joinpath(filename.parent, LAST_BT_RESULT_FN) file_dump_json(latest_filename, {'latest_backtest': str(filename.name)}) + def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict]) -> None: """ Stores backtest trade signal candles @@ -65,6 +66,7 @@ def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict] with open(filename, 'wb') as f: pickle.dump(candles, f) + def _get_line_floatfmt(stake_currency: str) -> List[str]: """ Generate floatformat (goes in line with _generate_result_line()) From a63affc5f14156b671c805de9256d3e611d05c93 Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 16:32:04 +0100 Subject: [PATCH 059/159] Fix flake8 complaints --- freqtrade/optimize/backtesting.py | 13 ++++++++----- freqtrade/optimize/optimize_reports.py | 3 ++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index f19cd488e..7e19e26e4 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -8,7 +8,6 @@ from collections import defaultdict from copy import deepcopy from datetime import datetime, timedelta, timezone from typing import Any, Dict, List, Optional, Tuple -import pickle from numpy import nan from pandas import DataFrame @@ -20,14 +19,16 @@ from freqtrade.data import history from freqtrade.data.btanalysis import find_existing_backtest_stats, trade_list_to_dataframe from freqtrade.data.converter import trim_dataframe, trim_dataframes from freqtrade.data.dataprovider import DataProvider -from freqtrade.enums import BacktestState, CandleType, ExitCheckTuple, ExitType, TradingMode, RunMode +from freqtrade.enums import (BacktestState, CandleType, ExitCheckTuple, ExitType, TradingMode, + RunMode) from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.misc import get_strategy_run_id from freqtrade.mixins import LoggingMixin from freqtrade.optimize.bt_progress import BTProgress from freqtrade.optimize.optimize_reports import (generate_backtest_stats, show_backtest_results, - store_backtest_stats, store_backtest_signal_candles) + store_backtest_stats, + store_backtest_signal_candles) from freqtrade.persistence import LocalTrade, Order, PairLocks, Trade from freqtrade.plugins.pairlistmanager import PairListManager from freqtrade.plugins.protectionmanager import ProtectionManager @@ -1075,7 +1076,8 @@ class Backtesting: }) self.all_results[self.strategy.get_strategy_name()] = results - if self.backtest_signal_candle_export_enable and self.dataprovider.runmode == RunMode.BACKTEST: + if self.backtest_signal_candle_export_enable and + self.dataprovider.runmode == RunMode.BACKTEST: signal_candles_only = {} for pair in preprocessed_tmp.keys(): signal_candles_only_df = DataFrame() @@ -1157,7 +1159,8 @@ class Backtesting: if self.config.get('export', 'none') == 'trades': store_backtest_stats(self.config['exportfilename'], self.results) - if self.backtest_signal_candle_export_enable and self.dataprovider.runmode == RunMode.BACKTEST: + if self.backtest_signal_candle_export_enable and + self.dataprovider.runmode == RunMode.BACKTEST: store_backtest_signal_candles(self.config['exportfilename'], self.processed_dfs) # Results may be mixed up now. Sort them so they follow --strategy-list order. diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index f870bd1f5..06b393b60 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -51,7 +51,8 @@ def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict] Stores backtest trade signal candles :param recordfilename: Path object, which can either be a filename or a directory. Filenames will be appended with a timestamp right before the suffix - while for directories, /backtest-result-_signals.pkl will be used as filename + while for directories, /backtest-result-_signals.pkl will be used + as filename :param stats: Dict containing the backtesting signal candles """ if recordfilename.is_dir(): From 7210a1173074915b76751085ff3df2f23b2a55aa Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 16:37:06 +0100 Subject: [PATCH 060/159] Fix flake8 complaints --- freqtrade/optimize/backtesting.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 7e19e26e4..839463218 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -131,7 +131,8 @@ class Backtesting: self.config['startup_candle_count'] = self.required_startup self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe) - self.backtest_signal_candle_export_enable = self.config.get('backtest_signal_candle_export_enable', False) + self.backtest_signal_candle_export_enable = self.config.get( + 'backtest_signal_candle_export_enable', False) self.trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT) # strategies which define "can_short=True" will fail to load in Spot mode. From b738c4e695e69d51a3827f3f99b42e40f0b01846 Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 16:49:20 +0100 Subject: [PATCH 061/159] Fix flake8 complaints --- freqtrade/optimize/backtesting.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 839463218..e9440f62c 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -20,7 +20,7 @@ from freqtrade.data.btanalysis import find_existing_backtest_stats, trade_list_t from freqtrade.data.converter import trim_dataframe, trim_dataframes from freqtrade.data.dataprovider import DataProvider from freqtrade.enums import (BacktestState, CandleType, ExitCheckTuple, ExitType, TradingMode, - RunMode) + RunMode) from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.misc import get_strategy_run_id @@ -1077,8 +1077,8 @@ class Backtesting: }) self.all_results[self.strategy.get_strategy_name()] = results - if self.backtest_signal_candle_export_enable and - self.dataprovider.runmode == RunMode.BACKTEST: + if self.backtest_signal_candle_export_enable and \ + self.dataprovider.runmode == RunMode.BACKTEST: signal_candles_only = {} for pair in preprocessed_tmp.keys(): signal_candles_only_df = DataFrame() @@ -1160,8 +1160,8 @@ class Backtesting: if self.config.get('export', 'none') == 'trades': store_backtest_stats(self.config['exportfilename'], self.results) - if self.backtest_signal_candle_export_enable and - self.dataprovider.runmode == RunMode.BACKTEST: + if self.backtest_signal_candle_export_enable and \ + self.dataprovider.runmode == RunMode.BACKTEST: store_backtest_signal_candles(self.config['exportfilename'], self.processed_dfs) # Results may be mixed up now. Sort them so they follow --strategy-list order. From 34fb8dacd7fb9083461ad2986b47d2d8480a7e05 Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 16 Apr 2022 17:03:24 +0100 Subject: [PATCH 062/159] Fix isort complaints --- freqtrade/optimize/backtesting.py | 8 ++++---- freqtrade/optimize/optimize_reports.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index e9440f62c..03a6cade0 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -19,16 +19,16 @@ from freqtrade.data import history from freqtrade.data.btanalysis import find_existing_backtest_stats, trade_list_to_dataframe from freqtrade.data.converter import trim_dataframe, trim_dataframes from freqtrade.data.dataprovider import DataProvider -from freqtrade.enums import (BacktestState, CandleType, ExitCheckTuple, ExitType, TradingMode, - RunMode) +from freqtrade.enums import (BacktestState, CandleType, ExitCheckTuple, ExitType, RunMode, + TradingMode) from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.misc import get_strategy_run_id from freqtrade.mixins import LoggingMixin from freqtrade.optimize.bt_progress import BTProgress from freqtrade.optimize.optimize_reports import (generate_backtest_stats, show_backtest_results, - store_backtest_stats, - store_backtest_signal_candles) + store_backtest_signal_candles, + store_backtest_stats) from freqtrade.persistence import LocalTrade, Order, PairLocks, Trade from freqtrade.plugins.pairlistmanager import PairListManager from freqtrade.plugins.protectionmanager import ProtectionManager diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 06b393b60..f0b2e2e71 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -1,9 +1,9 @@ import logging +import pickle from copy import deepcopy from datetime import datetime, timedelta, timezone from pathlib import Path from typing import Any, Dict, List, Union -import pickle from numpy import int64 from pandas import DataFrame, to_datetime From 591a2fb7fc7aa94df8cf38c6fc3dd001a3d02014 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 16 Apr 2022 21:47:44 -0600 Subject: [PATCH 063/159] switch notionalFloor -> minNotional and notionalCap -> maxNotional --- .../exchange/binance_leverage_tiers.json | 8616 ++++++++--------- freqtrade/exchange/exchange.py | 4 +- tests/exchange/test_binance.py | 104 +- tests/exchange/test_ccxt_compat.py | 16 +- tests/exchange/test_exchange.py | 20 +- tests/exchange/test_okx.py | 48 +- 6 files changed, 4404 insertions(+), 4404 deletions(-) diff --git a/freqtrade/exchange/binance_leverage_tiers.json b/freqtrade/exchange/binance_leverage_tiers.json index c0bb965d0..ddffe1250 100644 --- a/freqtrade/exchange/binance_leverage_tiers.json +++ b/freqtrade/exchange/binance_leverage_tiers.json @@ -2,90 +2,90 @@ "RAY/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -94,105 +94,105 @@ "SUSHI/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 50000000, + "minNotional": 2000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "2000000", + "maxNotional": "50000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -201,90 +201,90 @@ "CVC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -293,90 +293,90 @@ "BTS/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -385,90 +385,90 @@ "HOT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -477,90 +477,90 @@ "ZRX/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -569,90 +569,90 @@ "QTUM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -661,90 +661,90 @@ "IOTA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -753,150 +753,150 @@ "BTC/BUSD": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.004, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.004", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.005, "maxLeverage": 25, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.005", "cum": "50.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.01, "maxLeverage": 20, "info": { "bracket": "3", "initialLeverage": "20", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.01", "cum": "1300.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 7500000, + "minNotional": 1000000, + "maxNotional": 7500000, "maintenanceMarginRate": 0.025, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "7500000", - "notionalFloor": "1000000", + "maxNotional": "7500000", + "minNotional": "1000000", "maintMarginRatio": "0.025", "cum": "16300.0" } }, { "tier": 5, - "notionalFloor": 7500000, - "notionalCap": 40000000, + "minNotional": 7500000, + "maxNotional": 40000000, "maintenanceMarginRate": 0.05, "maxLeverage": 6, "info": { "bracket": "5", "initialLeverage": "6", - "notionalCap": "40000000", - "notionalFloor": "7500000", + "maxNotional": "40000000", + "minNotional": "7500000", "maintMarginRatio": "0.05", "cum": "203800.0" } }, { "tier": 6, - "notionalFloor": 40000000, - "notionalCap": 100000000, + "minNotional": 40000000, + "maxNotional": 100000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "100000000", - "notionalFloor": "40000000", + "maxNotional": "100000000", + "minNotional": "40000000", "maintMarginRatio": "0.1", "cum": "2203800.0" } }, { "tier": 7, - "notionalFloor": 100000000, - "notionalCap": 200000000, + "minNotional": 100000000, + "maxNotional": 200000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "7", "initialLeverage": "4", - "notionalCap": "200000000", - "notionalFloor": "100000000", + "maxNotional": "200000000", + "minNotional": "100000000", "maintMarginRatio": "0.125", "cum": "4703800.0" } }, { "tier": 8, - "notionalFloor": 200000000, - "notionalCap": 400000000, + "minNotional": 200000000, + "maxNotional": 400000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "8", "initialLeverage": "3", - "notionalCap": "400000000", - "notionalFloor": "200000000", + "maxNotional": "400000000", + "minNotional": "200000000", "maintMarginRatio": "0.15", "cum": "9703800.0" } }, { "tier": 9, - "notionalFloor": 400000000, - "notionalCap": 600000000, + "minNotional": 400000000, + "maxNotional": 600000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "9", "initialLeverage": "2", - "notionalCap": "600000000", - "notionalFloor": "400000000", + "maxNotional": "600000000", + "minNotional": "400000000", "maintMarginRatio": "0.25", "cum": "4.97038E7" } }, { "tier": 10, - "notionalFloor": 600000000, - "notionalCap": 1000000000, + "minNotional": 600000000, + "maxNotional": 1000000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "10", "initialLeverage": "1", - "notionalCap": "1000000000", - "notionalFloor": "600000000", + "maxNotional": "1000000000", + "minNotional": "600000000", "maintMarginRatio": "0.5", "cum": "1.997038E8" } @@ -905,90 +905,90 @@ "WAVES/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -997,135 +997,135 @@ "ADA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -1134,90 +1134,90 @@ "LIT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -1226,90 +1226,90 @@ "NU/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -1318,135 +1318,135 @@ "XTZ/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -1455,135 +1455,135 @@ "BNB/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -1592,90 +1592,90 @@ "AKRO/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.012, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.012", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "65.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "690.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5690.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11940.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386940.0" } @@ -1684,90 +1684,90 @@ "HNT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -1776,135 +1776,135 @@ "ETC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -1913,135 +1913,135 @@ "XMR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -2050,90 +2050,90 @@ "YFI/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -2142,90 +2142,90 @@ "FTT/BUSD": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 100000, + "minNotional": 0, + "maxNotional": 100000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", + "maxNotional": "100000", + "minNotional": "0", "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.05", "cum": "2500.0" } }, { "tier": 3, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.1", "cum": "27500.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "4", "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.15", "cum": "77500.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.25", "cum": "277500.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 30000000, + "minNotional": 5000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", + "maxNotional": "30000000", + "minNotional": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" } @@ -2234,120 +2234,120 @@ "BTCUSDT_210326": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 9223372036854776000, + "minNotional": 10000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "9223372036854775807", - "notionalFloor": "10000000", + "maxNotional": "9223372036854775807", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } @@ -2356,150 +2356,150 @@ "ETH/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.005, "maxLeverage": 100, "info": { "bracket": "1", "initialLeverage": "100", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.005", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 100000, + "minNotional": 10000, + "maxNotional": 100000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "2", "initialLeverage": "75", - "notionalCap": "100000", - "notionalFloor": "10000", + "maxNotional": "100000", + "minNotional": "10000", "maintMarginRatio": "0.0065", "cum": "15.0" } }, { "tier": 3, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "3", "initialLeverage": "50", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.01", "cum": "365.0" } }, { "tier": 4, - "notionalFloor": 500000, - "notionalCap": 1500000, + "minNotional": 500000, + "maxNotional": 1500000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "4", "initialLeverage": "25", - "notionalCap": "1500000", - "notionalFloor": "500000", + "maxNotional": "1500000", + "minNotional": "500000", "maintMarginRatio": "0.02", "cum": "5365.0" } }, { "tier": 5, - "notionalFloor": 1500000, - "notionalCap": 4000000, + "minNotional": 1500000, + "maxNotional": 4000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "5", "initialLeverage": "10", - "notionalCap": "4000000", - "notionalFloor": "1500000", + "maxNotional": "4000000", + "minNotional": "1500000", "maintMarginRatio": "0.05", "cum": "50365.0" } }, { "tier": 6, - "notionalFloor": 4000000, - "notionalCap": 10000000, + "minNotional": 4000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "10000000", - "notionalFloor": "4000000", + "maxNotional": "10000000", + "minNotional": "4000000", "maintMarginRatio": "0.1", "cum": "250365.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "7", "initialLeverage": "4", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.125", "cum": "500365.0" } }, { "tier": 8, - "notionalFloor": 20000000, - "notionalCap": 40000000, + "minNotional": 20000000, + "maxNotional": 40000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "8", "initialLeverage": "3", - "notionalCap": "40000000", - "notionalFloor": "20000000", + "maxNotional": "40000000", + "minNotional": "20000000", "maintMarginRatio": "0.15", "cum": "1000365.0" } }, { "tier": 9, - "notionalFloor": 40000000, - "notionalCap": 150000000, + "minNotional": 40000000, + "maxNotional": 150000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "9", "initialLeverage": "2", - "notionalCap": "150000000", - "notionalFloor": "40000000", + "maxNotional": "150000000", + "minNotional": "40000000", "maintMarginRatio": "0.25", "cum": "5000365.0" } }, { "tier": 10, - "notionalFloor": 150000000, - "notionalCap": 500000000, + "minNotional": 150000000, + "maxNotional": 500000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "10", "initialLeverage": "1", - "notionalCap": "500000000", - "notionalFloor": "150000000", + "maxNotional": "500000000", + "minNotional": "150000000", "maintMarginRatio": "0.5", "cum": "4.2500365E7" } @@ -2508,105 +2508,105 @@ "ALICE/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -2615,90 +2615,90 @@ "ALPHA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -2707,90 +2707,90 @@ "SFP/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -2799,90 +2799,90 @@ "REEF/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -2891,90 +2891,90 @@ "BAT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -2983,105 +2983,105 @@ "DOGE/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "7000.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "57000.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "107000.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.25", "cum": "732000.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 50000000, + "minNotional": 10000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "10000000", + "maxNotional": "50000000", + "minNotional": "10000000", "maintMarginRatio": "0.5", "cum": "3232000.0" } @@ -3090,135 +3090,135 @@ "TRX/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -3227,90 +3227,90 @@ "RLC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -3319,90 +3319,90 @@ "DOTECOUSDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.012, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.012", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "65.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "690.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5690.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11940.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 9223372036854776000, + "minNotional": 1000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "9223372036854775807", - "notionalFloor": "1000000", + "maxNotional": "9223372036854775807", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386940.0" } @@ -3411,90 +3411,90 @@ "BTCSTUSDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 9223372036854776000, + "minNotional": 1000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "9223372036854775807", - "notionalFloor": "1000000", + "maxNotional": "9223372036854775807", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -3503,90 +3503,90 @@ "STORJ/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -3595,90 +3595,90 @@ "SNX/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -3687,90 +3687,90 @@ "ETHUSDT_210625": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 250000, + "minNotional": 0, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "0", + "maxNotional": "250000", + "minNotional": "0", "maintMarginRatio": "0.02", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "7500.0" } }, { "tier": 3, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "57500.0" } }, { "tier": 4, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "107500.0" } }, { "tier": 5, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "5", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "232500.0" } }, { "tier": 6, - "notionalFloor": 10000000, - "notionalCap": 9223372036854776000, + "minNotional": 10000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "9223372036854775807", - "notionalFloor": "10000000", + "maxNotional": "9223372036854775807", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1232500.0" } @@ -3779,90 +3779,90 @@ "1000XEC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -3871,90 +3871,90 @@ "AUDIO/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -3963,135 +3963,135 @@ "XLM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -4100,135 +4100,135 @@ "BTCBUSD_210129": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.004, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.004", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.005, "maxLeverage": 15, "info": { "bracket": "2", "initialLeverage": "15", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.005", "cum": "5.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.01, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.01", "cum": "130.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.025, "maxLeverage": 7, "info": { "bracket": "4", "initialLeverage": "7", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.025", "cum": "1630.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 2000000, + "minNotional": 500000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.05, "maxLeverage": 6, "info": { "bracket": "5", "initialLeverage": "6", - "notionalCap": "2000000", - "notionalFloor": "500000", + "maxNotional": "2000000", + "minNotional": "500000", "maintMarginRatio": "0.05", "cum": "14130.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.1", "cum": "114130.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "7", "initialLeverage": "4", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.125", "cum": "239130.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "8", "initialLeverage": "3", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.15", "cum": "489130.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 9223372036854776000, + "minNotional": 20000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "9", "initialLeverage": "2", - "notionalCap": "9223372036854775807", - "notionalFloor": "20000000", + "maxNotional": "9223372036854775807", + "minNotional": "20000000", "maintMarginRatio": "0.25", "cum": "2489130.0" } @@ -4237,90 +4237,90 @@ "IOTX/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -4329,90 +4329,90 @@ "NEO/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -4421,90 +4421,90 @@ "UNFI/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -4513,105 +4513,105 @@ "SAND/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -4620,90 +4620,90 @@ "DASH/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -4712,90 +4712,90 @@ "KAVA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -4804,90 +4804,90 @@ "RUNE/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -4896,90 +4896,90 @@ "CTK/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -4988,135 +4988,135 @@ "LINK/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -5125,105 +5125,105 @@ "CELR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -5232,90 +5232,90 @@ "RSR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -5324,90 +5324,90 @@ "ADA/BUSD": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 100000, + "minNotional": 0, + "maxNotional": 100000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", + "maxNotional": "100000", + "minNotional": "0", "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.05", "cum": "2500.0" } }, { "tier": 3, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.1", "cum": "27500.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "4", "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.15", "cum": "77500.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.25", "cum": "277500.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 30000000, + "minNotional": 5000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", + "maxNotional": "30000000", + "minNotional": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" } @@ -5416,90 +5416,90 @@ "DGB/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -5508,90 +5508,90 @@ "SKL/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -5600,90 +5600,90 @@ "REN/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -5692,90 +5692,90 @@ "LPT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -5784,90 +5784,90 @@ "TOMO/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -5876,90 +5876,90 @@ "MTL/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -5968,135 +5968,135 @@ "LTC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -6105,90 +6105,90 @@ "DODO/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -6197,90 +6197,90 @@ "EGLD/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 50000000, + "minNotional": 1000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "1000000", + "maxNotional": "50000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -6289,90 +6289,90 @@ "KSM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -6381,90 +6381,90 @@ "BNB/BUSD": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 100000, + "minNotional": 0, + "maxNotional": 100000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", + "maxNotional": "100000", + "minNotional": "0", "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.05", "cum": "2500.0" } }, { "tier": 3, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.1", "cum": "27500.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "4", "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.15", "cum": "77500.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.25", "cum": "277500.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 30000000, + "minNotional": 5000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", + "maxNotional": "30000000", + "minNotional": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" } @@ -6473,90 +6473,90 @@ "BTCUSDT_210625": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 250000, + "minNotional": 0, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "0", + "maxNotional": "250000", + "minNotional": "0", "maintMarginRatio": "0.02", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "7500.0" } }, { "tier": 3, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "57500.0" } }, { "tier": 4, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "107500.0" } }, { "tier": 5, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "5", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "232500.0" } }, { "tier": 6, - "notionalFloor": 10000000, - "notionalCap": 9223372036854776000, + "minNotional": 10000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "9223372036854775807", - "notionalFloor": "10000000", + "maxNotional": "9223372036854775807", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1232500.0" } @@ -6565,90 +6565,90 @@ "ONT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -6657,105 +6657,105 @@ "VET/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -6764,90 +6764,90 @@ "TRB/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -6856,105 +6856,105 @@ "MANA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -6963,90 +6963,90 @@ "COTI/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -7055,90 +7055,90 @@ "CHR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -7147,105 +7147,105 @@ "ETHUSDT_210924": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 250000, + "minNotional": 0, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "0", + "maxNotional": "250000", + "minNotional": "0", "maintMarginRatio": "0.02", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "7500.0" } }, { "tier": 3, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "57500.0" } }, { "tier": 4, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "107500.0" } }, { "tier": 5, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "5", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "232500.0" } }, { "tier": 6, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1232500.0" } }, { "tier": 7, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6232500.0" } @@ -7254,90 +7254,90 @@ "BAKE/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -7346,90 +7346,90 @@ "GRT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -7438,105 +7438,105 @@ "ETHUSDT_220325": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 375000, + "minNotional": 0, + "maxNotional": 375000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "375000", - "notionalFloor": "0", + "maxNotional": "375000", + "minNotional": "0", "maintMarginRatio": "0.02", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 375000, - "notionalCap": 2000000, + "minNotional": 375000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "2000000", - "notionalFloor": "375000", + "maxNotional": "2000000", + "minNotional": "375000", "maintMarginRatio": "0.05", "cum": "11250.0" } }, { "tier": 3, - "notionalFloor": 2000000, - "notionalCap": 4000000, + "minNotional": 2000000, + "maxNotional": 4000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "4000000", - "notionalFloor": "2000000", + "maxNotional": "4000000", + "minNotional": "2000000", "maintMarginRatio": "0.1", "cum": "111250.0" } }, { "tier": 4, - "notionalFloor": 4000000, - "notionalCap": 10000000, + "minNotional": 4000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "10000000", - "notionalFloor": "4000000", + "maxNotional": "10000000", + "minNotional": "4000000", "maintMarginRatio": "0.125", "cum": "211250.0" } }, { "tier": 5, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "5", "initialLeverage": "3", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.15", "cum": "461250.0" } }, { "tier": 6, - "notionalFloor": 20000000, - "notionalCap": 40000000, + "minNotional": 20000000, + "maxNotional": 40000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "40000000", - "notionalFloor": "20000000", + "maxNotional": "40000000", + "minNotional": "20000000", "maintMarginRatio": "0.25", "cum": "2461250.0" } }, { "tier": 7, - "notionalFloor": 40000000, - "notionalCap": 400000000, + "minNotional": 40000000, + "maxNotional": 400000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "400000000", - "notionalFloor": "40000000", + "maxNotional": "400000000", + "minNotional": "40000000", "maintMarginRatio": "0.5", "cum": "1.246125E7" } @@ -7545,90 +7545,90 @@ "FLM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -7637,90 +7637,90 @@ "MASK/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -7729,135 +7729,135 @@ "EOS/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -7866,105 +7866,105 @@ "ETHUSDT_211231": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 375000, + "minNotional": 0, + "maxNotional": 375000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "375000", - "notionalFloor": "0", + "maxNotional": "375000", + "minNotional": "0", "maintMarginRatio": "0.02", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 375000, - "notionalCap": 2000000, + "minNotional": 375000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "2000000", - "notionalFloor": "375000", + "maxNotional": "2000000", + "minNotional": "375000", "maintMarginRatio": "0.05", "cum": "11250.0" } }, { "tier": 3, - "notionalFloor": 2000000, - "notionalCap": 4000000, + "minNotional": 2000000, + "maxNotional": 4000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "4000000", - "notionalFloor": "2000000", + "maxNotional": "4000000", + "minNotional": "2000000", "maintMarginRatio": "0.1", "cum": "111250.0" } }, { "tier": 4, - "notionalFloor": 4000000, - "notionalCap": 10000000, + "minNotional": 4000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "10000000", - "notionalFloor": "4000000", + "maxNotional": "10000000", + "minNotional": "4000000", "maintMarginRatio": "0.125", "cum": "211250.0" } }, { "tier": 5, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "5", "initialLeverage": "3", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.15", "cum": "461250.0" } }, { "tier": 6, - "notionalFloor": 20000000, - "notionalCap": 40000000, + "minNotional": 20000000, + "maxNotional": 40000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "40000000", - "notionalFloor": "20000000", + "maxNotional": "40000000", + "minNotional": "20000000", "maintMarginRatio": "0.25", "cum": "2461250.0" } }, { "tier": 7, - "notionalFloor": 40000000, - "notionalCap": 400000000, + "minNotional": 40000000, + "maxNotional": 400000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "400000000", - "notionalFloor": "40000000", + "maxNotional": "400000000", + "minNotional": "40000000", "maintMarginRatio": "0.5", "cum": "1.246125E7" } @@ -7973,90 +7973,90 @@ "OGN/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8065,90 +8065,90 @@ "SC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8157,90 +8157,90 @@ "BAL/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8249,90 +8249,90 @@ "STMX/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8341,90 +8341,90 @@ "BTTUSDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8433,120 +8433,120 @@ "LUNA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "500.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8000.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58000.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108000.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.1665, "maxLeverage": 3, "info": { "bracket": "6", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.1665", "cum": "315500.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 15000000, + "minNotional": 10000000, + "maxNotional": 15000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "7", "initialLeverage": "2", - "notionalCap": "15000000", - "notionalFloor": "10000000", + "maxNotional": "15000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1150500.0" } }, { "tier": 8, - "notionalFloor": 15000000, - "notionalCap": 50000000, + "minNotional": 15000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "8", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "15000000", + "maxNotional": "50000000", + "minNotional": "15000000", "maintMarginRatio": "0.5", "cum": "4900500.0" } @@ -8555,90 +8555,90 @@ "DENT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8647,90 +8647,90 @@ "1000BTTC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8739,90 +8739,90 @@ "KNC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8831,90 +8831,90 @@ "SRM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -8923,105 +8923,105 @@ "ENJ/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -9030,90 +9030,90 @@ "C98/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -9122,90 +9122,90 @@ "ZEN/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -9214,105 +9214,105 @@ "ATOM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -9321,105 +9321,105 @@ "NEAR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -9428,90 +9428,90 @@ "SOL/BUSD": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 100000, + "minNotional": 0, + "maxNotional": 100000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", + "maxNotional": "100000", + "minNotional": "0", "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.05", "cum": "2500.0" } }, { "tier": 3, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.1", "cum": "27500.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "4", "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.15", "cum": "77500.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.25", "cum": "277500.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 30000000, + "minNotional": 5000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", + "maxNotional": "30000000", + "minNotional": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" } @@ -9520,90 +9520,90 @@ "ENS/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -9612,135 +9612,135 @@ "BCH/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -9749,90 +9749,90 @@ "ATA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -9841,90 +9841,90 @@ "IOST/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -9933,90 +9933,90 @@ "HBAR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -10025,105 +10025,105 @@ "ZEC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -10132,105 +10132,105 @@ "1000SHIB/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -10239,90 +10239,90 @@ "TLM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -10331,90 +10331,90 @@ "ANT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -10423,90 +10423,90 @@ "BZRXUSDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -10515,150 +10515,150 @@ "ETH/BUSD": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 25000, + "minNotional": 0, + "maxNotional": 25000, "maintenanceMarginRate": 0.004, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "25000", - "notionalFloor": "0", + "maxNotional": "25000", + "minNotional": "0", "maintMarginRatio": "0.004", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.005, "maxLeverage": 25, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.005", "cum": "25.0" } }, { "tier": 3, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.01, "maxLeverage": 20, "info": { "bracket": "3", "initialLeverage": "20", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.01", "cum": "525.0" } }, { "tier": 4, - "notionalFloor": 500000, - "notionalCap": 1500000, + "minNotional": 500000, + "maxNotional": 1500000, "maintenanceMarginRate": 0.025, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1500000", - "notionalFloor": "500000", + "maxNotional": "1500000", + "minNotional": "500000", "maintMarginRatio": "0.025", "cum": "8025.0" } }, { "tier": 5, - "notionalFloor": 1500000, - "notionalCap": 4000000, + "minNotional": 1500000, + "maxNotional": 4000000, "maintenanceMarginRate": 0.05, "maxLeverage": 6, "info": { "bracket": "5", "initialLeverage": "6", - "notionalCap": "4000000", - "notionalFloor": "1500000", + "maxNotional": "4000000", + "minNotional": "1500000", "maintMarginRatio": "0.05", "cum": "45525.0" } }, { "tier": 6, - "notionalFloor": 4000000, - "notionalCap": 10000000, + "minNotional": 4000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "10000000", - "notionalFloor": "4000000", + "maxNotional": "10000000", + "minNotional": "4000000", "maintMarginRatio": "0.1", "cum": "245525.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "7", "initialLeverage": "4", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.125", "cum": "495525.0" } }, { "tier": 8, - "notionalFloor": 20000000, - "notionalCap": 40000000, + "minNotional": 20000000, + "maxNotional": 40000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "8", "initialLeverage": "3", - "notionalCap": "40000000", - "notionalFloor": "20000000", + "maxNotional": "40000000", + "minNotional": "20000000", "maintMarginRatio": "0.15", "cum": "995525.0" } }, { "tier": 9, - "notionalFloor": 40000000, - "notionalCap": 150000000, + "minNotional": 40000000, + "maxNotional": 150000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "9", "initialLeverage": "2", - "notionalCap": "150000000", - "notionalFloor": "40000000", + "maxNotional": "150000000", + "minNotional": "40000000", "maintMarginRatio": "0.25", "cum": "4995525.0" } }, { "tier": 10, - "notionalFloor": 150000000, - "notionalCap": 500000000, + "minNotional": 150000000, + "maxNotional": 500000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "10", "initialLeverage": "1", - "notionalCap": "500000000", - "notionalFloor": "150000000", + "maxNotional": "500000000", + "minNotional": "150000000", "maintMarginRatio": "0.5", "cum": "4.2495525E7" } @@ -10667,105 +10667,105 @@ "GALA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -10774,120 +10774,120 @@ "AAVE/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "500.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8000.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58000.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108000.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.1665, "maxLeverage": 3, "info": { "bracket": "6", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.1665", "cum": "315500.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "7", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1150500.0" } }, { "tier": 8, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "8", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6150500.0" } @@ -10896,90 +10896,90 @@ "GTC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -10988,105 +10988,105 @@ "ALGO/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -11095,90 +11095,90 @@ "ICP/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -11187,105 +11187,105 @@ "BTCUSDT_210924": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 250000, + "minNotional": 0, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "0", + "maxNotional": "250000", + "minNotional": "0", "maintMarginRatio": "0.02", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "7500.0" } }, { "tier": 3, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "57500.0" } }, { "tier": 4, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "107500.0" } }, { "tier": 5, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "5", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "232500.0" } }, { "tier": 6, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1232500.0" } }, { "tier": 7, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6232500.0" } @@ -11294,105 +11294,105 @@ "LRC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -11401,105 +11401,105 @@ "AVAX/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 750000, + "minNotional": 500000, + "maxNotional": 750000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "750000", - "notionalFloor": "500000", + "maxNotional": "750000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 750000, - "notionalCap": 1000000, + "minNotional": 750000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "750000", + "maxNotional": "1000000", + "minNotional": "750000", "maintMarginRatio": "0.25", "cum": "123250.0" } }, { "tier": 7, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "373250.0" } @@ -11508,105 +11508,105 @@ "BTCUSDT_220325": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 375000, + "minNotional": 0, + "maxNotional": 375000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "375000", - "notionalFloor": "0", + "maxNotional": "375000", + "minNotional": "0", "maintMarginRatio": "0.02", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 375000, - "notionalCap": 2000000, + "minNotional": 375000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "2000000", - "notionalFloor": "375000", + "maxNotional": "2000000", + "minNotional": "375000", "maintMarginRatio": "0.05", "cum": "11250.0" } }, { "tier": 3, - "notionalFloor": 2000000, - "notionalCap": 4000000, + "minNotional": 2000000, + "maxNotional": 4000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "4000000", - "notionalFloor": "2000000", + "maxNotional": "4000000", + "minNotional": "2000000", "maintMarginRatio": "0.1", "cum": "111250.0" } }, { "tier": 4, - "notionalFloor": 4000000, - "notionalCap": 10000000, + "minNotional": 4000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "10000000", - "notionalFloor": "4000000", + "maxNotional": "10000000", + "minNotional": "4000000", "maintMarginRatio": "0.125", "cum": "211250.0" } }, { "tier": 5, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "5", "initialLeverage": "3", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.15", "cum": "461250.0" } }, { "tier": 6, - "notionalFloor": 20000000, - "notionalCap": 40000000, + "minNotional": 20000000, + "maxNotional": 40000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "40000000", - "notionalFloor": "20000000", + "maxNotional": "40000000", + "minNotional": "20000000", "maintMarginRatio": "0.25", "cum": "2461250.0" } }, { "tier": 7, - "notionalFloor": 40000000, - "notionalCap": 400000000, + "minNotional": 40000000, + "maxNotional": 400000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "400000000", - "notionalFloor": "40000000", + "maxNotional": "400000000", + "minNotional": "40000000", "maintMarginRatio": "0.5", "cum": "1.246125E7" } @@ -11615,90 +11615,90 @@ "ARPA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -11707,90 +11707,90 @@ "CELO/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -11799,90 +11799,90 @@ "ROSE/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -11891,105 +11891,105 @@ "MATIC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 750000, + "minNotional": 500000, + "maxNotional": 750000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "750000", - "notionalFloor": "500000", + "maxNotional": "750000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 750000, - "notionalCap": 1000000, + "minNotional": 750000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "750000", + "maxNotional": "1000000", + "minNotional": "750000", "maintMarginRatio": "0.25", "cum": "123250.0" } }, { "tier": 7, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "373250.0" } @@ -11998,90 +11998,90 @@ "1INCH/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.012, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.012", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "65.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "690.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5690.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11940.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 100000000, + "minNotional": 1000000, + "maxNotional": 100000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "100000000", - "notionalFloor": "1000000", + "maxNotional": "100000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386940.0" } @@ -12090,90 +12090,90 @@ "MKR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -12182,90 +12182,90 @@ "PEOPLE/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -12274,120 +12274,120 @@ "THETA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "500.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8000.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58000.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108000.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.1665, "maxLeverage": 3, "info": { "bracket": "6", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.1665", "cum": "315500.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "7", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1150500.0" } }, { "tier": 8, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "8", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6150500.0" } @@ -12396,120 +12396,120 @@ "UNI/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "500.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8000.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58000.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108000.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.1665, "maxLeverage": 3, "info": { "bracket": "6", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.1665", "cum": "315500.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "7", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1150500.0" } }, { "tier": 8, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "8", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6150500.0" } @@ -12518,120 +12518,120 @@ "ETHUSDT_210326": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 9223372036854776000, + "minNotional": 10000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "9223372036854775807", - "notionalFloor": "10000000", + "maxNotional": "9223372036854775807", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } @@ -12640,90 +12640,90 @@ "LINA/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -12732,90 +12732,90 @@ "AR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -12824,90 +12824,90 @@ "RVN/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -12916,120 +12916,120 @@ "FIL/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "500.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8000.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58000.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108000.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.1665, "maxLeverage": 3, "info": { "bracket": "6", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.1665", "cum": "315500.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "7", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1150500.0" } }, { "tier": 8, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "8", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6150500.0" } @@ -13038,90 +13038,90 @@ "NKN/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -13130,90 +13130,90 @@ "KLAY/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -13222,90 +13222,90 @@ "DEFI/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -13314,90 +13314,90 @@ "COMP/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -13406,90 +13406,90 @@ "BTCDOM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -13498,105 +13498,105 @@ "SOL/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "7000.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "57000.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "107000.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.25", "cum": "732000.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 50000000, + "minNotional": 10000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "10000000", + "maxNotional": "50000000", + "minNotional": "10000000", "maintMarginRatio": "0.5", "cum": "3232000.0" } @@ -13605,150 +13605,150 @@ "BTC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.004, "maxLeverage": 125, "info": { "bracket": "1", "initialLeverage": "125", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.004", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.005, "maxLeverage": 100, "info": { "bracket": "2", "initialLeverage": "100", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.005", "cum": "50.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "3", "initialLeverage": "50", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.01", "cum": "1300.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 7500000, + "minNotional": 1000000, + "maxNotional": 7500000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "4", "initialLeverage": "20", - "notionalCap": "7500000", - "notionalFloor": "1000000", + "maxNotional": "7500000", + "minNotional": "1000000", "maintMarginRatio": "0.025", "cum": "16300.0" } }, { "tier": 5, - "notionalFloor": 7500000, - "notionalCap": 40000000, + "minNotional": 7500000, + "maxNotional": 40000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "5", "initialLeverage": "10", - "notionalCap": "40000000", - "notionalFloor": "7500000", + "maxNotional": "40000000", + "minNotional": "7500000", "maintMarginRatio": "0.05", "cum": "203800.0" } }, { "tier": 6, - "notionalFloor": 40000000, - "notionalCap": 100000000, + "minNotional": 40000000, + "maxNotional": 100000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "100000000", - "notionalFloor": "40000000", + "maxNotional": "100000000", + "minNotional": "40000000", "maintMarginRatio": "0.1", "cum": "2203800.0" } }, { "tier": 7, - "notionalFloor": 100000000, - "notionalCap": 200000000, + "minNotional": 100000000, + "maxNotional": 200000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "7", "initialLeverage": "4", - "notionalCap": "200000000", - "notionalFloor": "100000000", + "maxNotional": "200000000", + "minNotional": "100000000", "maintMarginRatio": "0.125", "cum": "4703800.0" } }, { "tier": 8, - "notionalFloor": 200000000, - "notionalCap": 400000000, + "minNotional": 200000000, + "maxNotional": 400000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "8", "initialLeverage": "3", - "notionalCap": "400000000", - "notionalFloor": "200000000", + "maxNotional": "400000000", + "minNotional": "200000000", "maintMarginRatio": "0.15", "cum": "9703800.0" } }, { "tier": 9, - "notionalFloor": 400000000, - "notionalCap": 600000000, + "minNotional": 400000000, + "maxNotional": 600000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "9", "initialLeverage": "2", - "notionalCap": "600000000", - "notionalFloor": "400000000", + "maxNotional": "600000000", + "minNotional": "400000000", "maintMarginRatio": "0.25", "cum": "4.97038E7" } }, { "tier": 10, - "notionalFloor": 600000000, - "notionalCap": 1000000000, + "minNotional": 600000000, + "maxNotional": 1000000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "10", "initialLeverage": "1", - "notionalCap": "1000000000", - "notionalFloor": "600000000", + "maxNotional": "1000000000", + "minNotional": "600000000", "maintMarginRatio": "0.5", "cum": "1.997038E8" } @@ -13757,90 +13757,90 @@ "OMG/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.024, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.024", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "5.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "630.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5630.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11880.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 10000000, + "minNotional": 1000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "10000000", - "notionalFloor": "1000000", + "maxNotional": "10000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386880.0" } @@ -13849,90 +13849,90 @@ "ICX/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -13941,90 +13941,90 @@ "BLZ/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -14033,105 +14033,105 @@ "BTCUSDT_211231": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 375000, + "minNotional": 0, + "maxNotional": 375000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "375000", - "notionalFloor": "0", + "maxNotional": "375000", + "minNotional": "0", "maintMarginRatio": "0.02", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 375000, - "notionalCap": 2000000, + "minNotional": 375000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "2000000", - "notionalFloor": "375000", + "maxNotional": "2000000", + "minNotional": "375000", "maintMarginRatio": "0.05", "cum": "11250.0" } }, { "tier": 3, - "notionalFloor": 2000000, - "notionalCap": 4000000, + "minNotional": 2000000, + "maxNotional": 4000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "4000000", - "notionalFloor": "2000000", + "maxNotional": "4000000", + "minNotional": "2000000", "maintMarginRatio": "0.1", "cum": "111250.0" } }, { "tier": 4, - "notionalFloor": 4000000, - "notionalCap": 10000000, + "minNotional": 4000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "4", "initialLeverage": "4", - "notionalCap": "10000000", - "notionalFloor": "4000000", + "maxNotional": "10000000", + "minNotional": "4000000", "maintMarginRatio": "0.125", "cum": "211250.0" } }, { "tier": 5, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "5", "initialLeverage": "3", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.15", "cum": "461250.0" } }, { "tier": 6, - "notionalFloor": 20000000, - "notionalCap": 40000000, + "minNotional": 20000000, + "maxNotional": 40000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "40000000", - "notionalFloor": "20000000", + "maxNotional": "40000000", + "minNotional": "20000000", "maintMarginRatio": "0.25", "cum": "2461250.0" } }, { "tier": 7, - "notionalFloor": 40000000, - "notionalCap": 400000000, + "minNotional": 40000000, + "maxNotional": 400000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "400000000", - "notionalFloor": "40000000", + "maxNotional": "400000000", + "minNotional": "40000000", "maintMarginRatio": "0.5", "cum": "1.246125E7" } @@ -14140,105 +14140,105 @@ "FTM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 750000, + "minNotional": 500000, + "maxNotional": 750000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "750000", - "notionalFloor": "500000", + "maxNotional": "750000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 750000, - "notionalCap": 1000000, + "minNotional": 750000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "750000", + "maxNotional": "1000000", + "minNotional": "750000", "maintMarginRatio": "0.25", "cum": "123250.0" } }, { "tier": 7, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "373250.0" } @@ -14247,90 +14247,90 @@ "YFII/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -14339,90 +14339,90 @@ "KEEP/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -14431,90 +14431,90 @@ "BAND/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -14523,135 +14523,135 @@ "BTCBUSD_210226": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.004, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.004", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.005, "maxLeverage": 15, "info": { "bracket": "2", "initialLeverage": "15", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.005", "cum": "5.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.01, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.01", "cum": "130.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.025, "maxLeverage": 7, "info": { "bracket": "4", "initialLeverage": "7", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.025", "cum": "1630.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 2000000, + "minNotional": 500000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.05, "maxLeverage": 6, "info": { "bracket": "5", "initialLeverage": "6", - "notionalCap": "2000000", - "notionalFloor": "500000", + "maxNotional": "2000000", + "minNotional": "500000", "maintMarginRatio": "0.05", "cum": "14130.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "6", "initialLeverage": "5", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.1", "cum": "114130.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "7", "initialLeverage": "4", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.125", "cum": "239130.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "8", "initialLeverage": "3", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.15", "cum": "489130.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 9223372036854776000, + "minNotional": 20000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "9", "initialLeverage": "2", - "notionalCap": "9223372036854775807", - "notionalFloor": "20000000", + "maxNotional": "9223372036854775807", + "minNotional": "20000000", "maintMarginRatio": "0.25", "cum": "2489130.0" } @@ -14660,90 +14660,90 @@ "XRP/BUSD": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 100000, + "minNotional": 0, + "maxNotional": 100000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", + "maxNotional": "100000", + "minNotional": "0", "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.05", "cum": "2500.0" } }, { "tier": 3, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.1", "cum": "27500.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "4", "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.15", "cum": "77500.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.25", "cum": "277500.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 30000000, + "minNotional": 5000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", + "maxNotional": "30000000", + "minNotional": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" } @@ -14752,90 +14752,90 @@ "DOGE/BUSD": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 100000, + "minNotional": 0, + "maxNotional": 100000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", + "maxNotional": "100000", + "minNotional": "0", "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.05", "cum": "2500.0" } }, { "tier": 3, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.1", "cum": "27500.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "4", "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.15", "cum": "77500.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.25", "cum": "277500.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 30000000, + "minNotional": 5000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", + "maxNotional": "30000000", + "minNotional": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" } @@ -14844,135 +14844,135 @@ "XRP/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 20000000, + "minNotional": 10000000, + "maxNotional": 20000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "20000000", - "notionalFloor": "10000000", + "maxNotional": "20000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 20000000, - "notionalCap": 50000000, + "minNotional": 20000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "20000000", + "maxNotional": "50000000", + "minNotional": "20000000", "maintMarginRatio": "0.5", "cum": "6233035.0" } @@ -14981,90 +14981,90 @@ "SXP/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -15073,105 +15073,105 @@ "CRV/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -15180,90 +15180,90 @@ "BEL/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -15272,135 +15272,135 @@ "DOT/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 10000, + "minNotional": 0, + "maxNotional": 10000, "maintenanceMarginRate": 0.0065, "maxLeverage": 75, "info": { "bracket": "1", "initialLeverage": "75", - "notionalCap": "10000", - "notionalFloor": "0", + "maxNotional": "10000", + "minNotional": "0", "maintMarginRatio": "0.0065", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 10000, - "notionalCap": 50000, + "minNotional": 10000, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "2", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "10000", + "maxNotional": "50000", + "minNotional": "10000", "maintMarginRatio": "0.01", "cum": "35.0" } }, { "tier": 3, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "3", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "535.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "4", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8035.0" } }, { "tier": 5, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "5", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58035.0" } }, { "tier": 6, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "6", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108035.0" } }, { "tier": 7, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "7", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.15", "cum": "233035.0" } }, { "tier": 8, - "notionalFloor": 10000000, - "notionalCap": 50000000, + "minNotional": 10000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "8", "initialLeverage": "2", - "notionalCap": "50000000", - "notionalFloor": "10000000", + "maxNotional": "50000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1233035.0" } }, { "tier": 9, - "notionalFloor": 50000000, - "notionalCap": 100000000, + "minNotional": 50000000, + "maxNotional": 100000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "100000000", - "notionalFloor": "50000000", + "maxNotional": "100000000", + "minNotional": "50000000", "maintMarginRatio": "0.5", "cum": "1.3733035E7" } @@ -15409,90 +15409,90 @@ "XEM/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -15501,105 +15501,105 @@ "ONE/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } @@ -15608,90 +15608,90 @@ "ZIL/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -15700,120 +15700,120 @@ "AXS/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 250000, + "minNotional": 50000, + "maxNotional": 250000, "maintenanceMarginRate": 0.02, "maxLeverage": 25, "info": { "bracket": "2", "initialLeverage": "25", - "notionalCap": "250000", - "notionalFloor": "50000", + "maxNotional": "250000", + "minNotional": "50000", "maintMarginRatio": "0.02", "cum": "500.0" } }, { "tier": 3, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.05", "cum": "8000.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.1", "cum": "58000.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.125", "cum": "108000.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 10000000, + "minNotional": 5000000, + "maxNotional": 10000000, "maintenanceMarginRate": 0.1665, "maxLeverage": 3, "info": { "bracket": "6", "initialLeverage": "3", - "notionalCap": "10000000", - "notionalFloor": "5000000", + "maxNotional": "10000000", + "minNotional": "5000000", "maintMarginRatio": "0.1665", "cum": "315500.0" } }, { "tier": 7, - "notionalFloor": 10000000, - "notionalCap": 15000000, + "minNotional": 10000000, + "maxNotional": 15000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "7", "initialLeverage": "2", - "notionalCap": "15000000", - "notionalFloor": "10000000", + "maxNotional": "15000000", + "minNotional": "10000000", "maintMarginRatio": "0.25", "cum": "1150500.0" } }, { "tier": 8, - "notionalFloor": 15000000, - "notionalCap": 50000000, + "minNotional": 15000000, + "maxNotional": 50000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "8", "initialLeverage": "1", - "notionalCap": "50000000", - "notionalFloor": "15000000", + "maxNotional": "50000000", + "minNotional": "15000000", "maintMarginRatio": "0.5", "cum": "4900500.0" } @@ -15822,105 +15822,105 @@ "DYDX/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 4000000, + "minNotional": 1000000, + "maxNotional": 4000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "4000000", - "notionalFloor": "1000000", + "maxNotional": "4000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 4000000, - "notionalCap": 30000000, + "minNotional": 4000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "4000000", + "maxNotional": "30000000", + "minNotional": "4000000", "maintMarginRatio": "0.5", "cum": "1154500.0" } @@ -15929,90 +15929,90 @@ "OCEAN/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -16021,90 +16021,90 @@ "CHZ/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.012, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.012", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "65.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "690.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5690.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11940.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386940.0" } @@ -16113,90 +16113,90 @@ "LENDUSDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 9223372036854776000, + "minNotional": 1000000, + "maxNotional": 9223372036854776000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "9223372036854775807", - "notionalFloor": "1000000", + "maxNotional": "9223372036854775807", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -16205,90 +16205,90 @@ "ANKR/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.012, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.012", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "65.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "690.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5690.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11940.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386940.0" } @@ -16297,90 +16297,90 @@ "DUSK/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } @@ -16389,90 +16389,90 @@ "CTSI/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 5000, + "minNotional": 0, + "maxNotional": 5000, "maintenanceMarginRate": 0.01, "maxLeverage": 25, "info": { "bracket": "1", "initialLeverage": "25", - "notionalCap": "5000", - "notionalFloor": "0", + "maxNotional": "5000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 5000, - "notionalCap": 25000, + "minNotional": 5000, + "maxNotional": 25000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "25000", - "notionalFloor": "5000", + "maxNotional": "25000", + "minNotional": "5000", "maintMarginRatio": "0.025", "cum": "75.0" } }, { "tier": 3, - "notionalFloor": 25000, - "notionalCap": 100000, + "minNotional": 25000, + "maxNotional": 100000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "100000", - "notionalFloor": "25000", + "maxNotional": "100000", + "minNotional": "25000", "maintMarginRatio": "0.05", "cum": "700.0" } }, { "tier": 4, - "notionalFloor": 100000, - "notionalCap": 250000, + "minNotional": 100000, + "maxNotional": 250000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "250000", - "notionalFloor": "100000", + "maxNotional": "250000", + "minNotional": "100000", "maintMarginRatio": "0.1", "cum": "5700.0" } }, { "tier": 5, - "notionalFloor": 250000, - "notionalCap": 1000000, + "minNotional": 250000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "250000", + "maxNotional": "1000000", + "minNotional": "250000", "maintMarginRatio": "0.125", "cum": "11950.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 30000000, + "minNotional": 1000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "1000000", + "maxNotional": "30000000", + "minNotional": "1000000", "maintMarginRatio": "0.5", "cum": "386950.0" } diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index e0da0878d..ab063762b 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -2137,8 +2137,8 @@ class Exchange: def parse_leverage_tier(self, tier) -> Dict: info = tier.get('info', {}) return { - 'min': tier['notionalFloor'], - 'max': tier['notionalCap'], + 'min': tier['minNotional'], + 'max': tier['maxNotional'], 'mmr': tier['maintenanceMarginRate'], 'lev': tier['maxLeverage'], 'maintAmt': float(info['cum']) if 'cum' in info else None, diff --git a/tests/exchange/test_binance.py b/tests/exchange/test_binance.py index c3950e459..5c8d7d3b0 100644 --- a/tests/exchange/test_binance.py +++ b/tests/exchange/test_binance.py @@ -169,90 +169,90 @@ def test_fill_leverage_tiers_binance(default_conf, mocker): 'ADA/BUSD': [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 100000, + "minNotional": 0, + "maxNotional": 100000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", + "maxNotional": "100000", + "minNotional": "0", "maintMarginRatio": "0.025", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 100000, - "notionalCap": 500000, + "minNotional": 100000, + "maxNotional": 500000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "2", "initialLeverage": "10", - "notionalCap": "500000", - "notionalFloor": "100000", + "maxNotional": "500000", + "minNotional": "100000", "maintMarginRatio": "0.05", "cum": "2500.0" } }, { "tier": 3, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "3", "initialLeverage": "5", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.1", "cum": "27500.0" } }, { "tier": 4, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.15, "maxLeverage": 3, "info": { "bracket": "4", "initialLeverage": "3", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.15", "cum": "77500.0" } }, { "tier": 5, - "notionalFloor": 2000000, - "notionalCap": 5000000, + "minNotional": 2000000, + "maxNotional": 5000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "5", "initialLeverage": "2", - "notionalCap": "5000000", - "notionalFloor": "2000000", + "maxNotional": "5000000", + "minNotional": "2000000", "maintMarginRatio": "0.25", "cum": "277500.0" } }, { "tier": 6, - "notionalFloor": 5000000, - "notionalCap": 30000000, + "minNotional": 5000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "6", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "5000000", + "maxNotional": "30000000", + "minNotional": "5000000", "maintMarginRatio": "0.5", "cum": "1527500.0" } @@ -261,105 +261,105 @@ def test_fill_leverage_tiers_binance(default_conf, mocker): "ZEC/USDT": [ { "tier": 1, - "notionalFloor": 0, - "notionalCap": 50000, + "minNotional": 0, + "maxNotional": 50000, "maintenanceMarginRate": 0.01, "maxLeverage": 50, "info": { "bracket": "1", "initialLeverage": "50", - "notionalCap": "50000", - "notionalFloor": "0", + "maxNotional": "50000", + "minNotional": "0", "maintMarginRatio": "0.01", "cum": "0.0" } }, { "tier": 2, - "notionalFloor": 50000, - "notionalCap": 150000, + "minNotional": 50000, + "maxNotional": 150000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "2", "initialLeverage": "20", - "notionalCap": "150000", - "notionalFloor": "50000", + "maxNotional": "150000", + "minNotional": "50000", "maintMarginRatio": "0.025", "cum": "750.0" } }, { "tier": 3, - "notionalFloor": 150000, - "notionalCap": 250000, + "minNotional": 150000, + "maxNotional": 250000, "maintenanceMarginRate": 0.05, "maxLeverage": 10, "info": { "bracket": "3", "initialLeverage": "10", - "notionalCap": "250000", - "notionalFloor": "150000", + "maxNotional": "250000", + "minNotional": "150000", "maintMarginRatio": "0.05", "cum": "4500.0" } }, { "tier": 4, - "notionalFloor": 250000, - "notionalCap": 500000, + "minNotional": 250000, + "maxNotional": 500000, "maintenanceMarginRate": 0.1, "maxLeverage": 5, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "500000", - "notionalFloor": "250000", + "maxNotional": "500000", + "minNotional": "250000", "maintMarginRatio": "0.1", "cum": "17000.0" } }, { "tier": 5, - "notionalFloor": 500000, - "notionalCap": 1000000, + "minNotional": 500000, + "maxNotional": 1000000, "maintenanceMarginRate": 0.125, "maxLeverage": 4, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "1000000", - "notionalFloor": "500000", + "maxNotional": "1000000", + "minNotional": "500000", "maintMarginRatio": "0.125", "cum": "29500.0" } }, { "tier": 6, - "notionalFloor": 1000000, - "notionalCap": 2000000, + "minNotional": 1000000, + "maxNotional": 2000000, "maintenanceMarginRate": 0.25, "maxLeverage": 2, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "maxNotional": "2000000", + "minNotional": "1000000", "maintMarginRatio": "0.25", "cum": "154500.0" } }, { "tier": 7, - "notionalFloor": 2000000, - "notionalCap": 30000000, + "minNotional": 2000000, + "maxNotional": 30000000, "maintenanceMarginRate": 0.5, "maxLeverage": 1, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "30000000", - "notionalFloor": "2000000", + "maxNotional": "30000000", + "minNotional": "2000000", "maintMarginRatio": "0.5", "cum": "654500.0" } diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 14e45c8b0..2a148c388 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -369,25 +369,25 @@ class TestCCXTExchange(): pair_tiers = leverage_tiers[futures_pair] assert len(pair_tiers) > 0 oldLeverage = float('inf') - oldMaintenanceMarginRate = oldNotionalFloor = oldNotionalCap = -1 + oldMaintenanceMarginRate = oldminNotional = oldmaxNotional = -1 for tier in pair_tiers: for key in [ 'maintenanceMarginRate', - 'notionalFloor', - 'notionalCap', + 'minNotional', + 'maxNotional', 'maxLeverage' ]: assert key in tier assert tier[key] >= 0.0 - assert tier['notionalCap'] > tier['notionalFloor'] + assert tier['maxNotional'] > tier['minNotional'] assert tier['maxLeverage'] <= oldLeverage assert tier['maintenanceMarginRate'] >= oldMaintenanceMarginRate - assert tier['notionalFloor'] > oldNotionalFloor - assert tier['notionalCap'] > oldNotionalCap + assert tier['minNotional'] > oldminNotional + assert tier['maxNotional'] > oldmaxNotional oldLeverage = tier['maxLeverage'] oldMaintenanceMarginRate = tier['maintenanceMarginRate'] - oldNotionalFloor = tier['notionalFloor'] - oldNotionalCap = tier['notionalCap'] + oldminNotional = tier['minNotional'] + oldmaxNotional = tier['maxNotional'] def test_ccxt_dry_run_liquidation_price(self, exchange_futures): futures, futures_name = exchange_futures diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index e99121489..a6918b6d4 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -4507,8 +4507,8 @@ def test_load_leverage_tiers(mocker, default_conf, leverage_tiers, exchange_name 'ADA/USDT:USDT': [ { 'tier': 1, - 'notionalFloor': 0, - 'notionalCap': 500, + 'minNotional': 0, + 'maxNotional': 500, 'maintenanceMarginRate': 0.02, 'maxLeverage': 75, 'info': { @@ -4548,8 +4548,8 @@ def test_load_leverage_tiers(mocker, default_conf, leverage_tiers, exchange_name 'ADA/USDT:USDT': [ { 'tier': 1, - 'notionalFloor': 0, - 'notionalCap': 500, + 'minNotional': 0, + 'maxNotional': 500, 'maintenanceMarginRate': 0.02, 'maxLeverage': 75, 'info': { @@ -4584,15 +4584,15 @@ def test_parse_leverage_tier(mocker, default_conf): tier = { "tier": 1, - "notionalFloor": 0, - "notionalCap": 100000, + "minNotional": 0, + "maxNotional": 100000, "maintenanceMarginRate": 0.025, "maxLeverage": 20, "info": { "bracket": "1", "initialLeverage": "20", - "notionalCap": "100000", - "notionalFloor": "0", + "maxNotional": "100000", + "minNotional": "0", "maintMarginRatio": "0.025", "cum": "0.0" } @@ -4608,8 +4608,8 @@ def test_parse_leverage_tier(mocker, default_conf): tier2 = { 'tier': 1, - 'notionalFloor': 0, - 'notionalCap': 2000, + 'minNotional': 0, + 'maxNotional': 2000, 'maintenanceMarginRate': 0.01, 'maxLeverage': 75, 'info': { diff --git a/tests/exchange/test_okx.py b/tests/exchange/test_okx.py index 8ecdf6904..37c1ea974 100644 --- a/tests/exchange/test_okx.py +++ b/tests/exchange/test_okx.py @@ -19,8 +19,8 @@ def test_get_maintenance_ratio_and_amt_okx( 'ETH/USDT:USDT': [ { 'tier': 1, - 'notionalFloor': 0, - 'notionalCap': 2000, + 'minNotional': 0, + 'maxNotional': 2000, 'maintenanceMarginRate': 0.01, 'maxLeverage': 75, 'info': { @@ -39,8 +39,8 @@ def test_get_maintenance_ratio_and_amt_okx( }, { 'tier': 2, - 'notionalFloor': 2001, - 'notionalCap': 4000, + 'minNotional': 2001, + 'maxNotional': 4000, 'maintenanceMarginRate': 0.015, 'maxLeverage': 50, 'info': { @@ -59,8 +59,8 @@ def test_get_maintenance_ratio_and_amt_okx( }, { 'tier': 3, - 'notionalFloor': 4001, - 'notionalCap': 8000, + 'minNotional': 4001, + 'maxNotional': 8000, 'maintenanceMarginRate': 0.02, 'maxLeverage': 20, 'info': { @@ -81,8 +81,8 @@ def test_get_maintenance_ratio_and_amt_okx( 'ADA/USDT:USDT': [ { 'tier': 1, - 'notionalFloor': 0, - 'notionalCap': 500, + 'minNotional': 0, + 'maxNotional': 500, 'maintenanceMarginRate': 0.02, 'maxLeverage': 75, 'info': { @@ -101,8 +101,8 @@ def test_get_maintenance_ratio_and_amt_okx( }, { 'tier': 2, - 'notionalFloor': 501, - 'notionalCap': 1000, + 'minNotional': 501, + 'maxNotional': 1000, 'maintenanceMarginRate': 0.025, 'maxLeverage': 50, 'info': { @@ -121,8 +121,8 @@ def test_get_maintenance_ratio_and_amt_okx( }, { 'tier': 3, - 'notionalFloor': 1001, - 'notionalCap': 2000, + 'minNotional': 1001, + 'maxNotional': 2000, 'maintenanceMarginRate': 0.03, 'maxLeverage': 20, 'info': { @@ -180,8 +180,8 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets): [ { 'tier': 1, - 'notionalFloor': 0, - 'notionalCap': 500, + 'minNotional': 0, + 'maxNotional': 500, 'maintenanceMarginRate': 0.02, 'maxLeverage': 75, 'info': { @@ -200,8 +200,8 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets): }, { 'tier': 2, - 'notionalFloor': 501, - 'notionalCap': 1000, + 'minNotional': 501, + 'maxNotional': 1000, 'maintenanceMarginRate': 0.025, 'maxLeverage': 50, 'info': { @@ -220,8 +220,8 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets): }, { 'tier': 3, - 'notionalFloor': 1001, - 'notionalCap': 2000, + 'minNotional': 1001, + 'maxNotional': 2000, 'maintenanceMarginRate': 0.03, 'maxLeverage': 20, 'info': { @@ -242,8 +242,8 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets): [ { 'tier': 1, - 'notionalFloor': 0, - 'notionalCap': 2000, + 'minNotional': 0, + 'maxNotional': 2000, 'maintenanceMarginRate': 0.01, 'maxLeverage': 75, 'info': { @@ -262,8 +262,8 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets): }, { 'tier': 2, - 'notionalFloor': 2001, - 'notionalCap': 4000, + 'minNotional': 2001, + 'maxNotional': 4000, 'maintenanceMarginRate': 0.015, 'maxLeverage': 50, 'info': { @@ -282,8 +282,8 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets): }, { 'tier': 3, - 'notionalFloor': 4001, - 'notionalCap': 8000, + 'minNotional': 4001, + 'maxNotional': 8000, 'maintenanceMarginRate': 0.02, 'maxLeverage': 20, 'info': { From 80b34deb4dd19eaebcc8e11fa22b815057de510d Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sun, 17 Apr 2022 14:38:34 -0600 Subject: [PATCH 064/159] bump ccxt to 1.79.69 to account for https://github.com/ccxt/ccxt/pull/12873" --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3f2d1b351..07bb04be3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.22.3 pandas==1.4.2 pandas-ta==0.3.14b -ccxt==1.78.62 +ccxt==1.79.69 # Pin cryptography for now due to rust build errors with piwheels cryptography==36.0.2 aiohttp==3.8.1 From a1e425a8013e881229bf8d61c7f2b5bcb686138e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 03:01:19 +0000 Subject: [PATCH 065/159] Bump fastapi from 0.75.1 to 0.75.2 Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.75.1 to 0.75.2. - [Release notes](https://github.com/tiangolo/fastapi/releases) - [Commits](https://github.com/tiangolo/fastapi/compare/0.75.1...0.75.2) --- updated-dependencies: - dependency-name: fastapi 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 3f2d1b351..2d23dd1ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,7 +31,7 @@ python-rapidjson==1.6 sdnotify==0.3.2 # API Server -fastapi==0.75.1 +fastapi==0.75.2 uvicorn==0.17.6 pyjwt==2.3.0 aiofiles==0.8.0 From 2ff18e78c40b13ae30ca47d8f2f29ce4c58e7767 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 03:01:22 +0000 Subject: [PATCH 066/159] Bump types-cachetools from 5.0.0 to 5.0.1 Bumps [types-cachetools](https://github.com/python/typeshed) from 5.0.0 to 5.0.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-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 03bb5e72d..764efd6ed 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -22,7 +22,7 @@ time-machine==2.6.0 nbconvert==6.4.5 # mypy types -types-cachetools==5.0.0 +types-cachetools==5.0.1 types-filelock==3.2.5 types-requests==2.27.16 types-tabulate==0.8.6 From 7d88dcb5f46d56296ae1cc8b2b0b4d4f52e3e0f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 03:01:24 +0000 Subject: [PATCH 067/159] Bump types-tabulate from 0.8.6 to 0.8.7 Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.6 to 0.8.7. - [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 03bb5e72d..489879978 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -25,7 +25,7 @@ nbconvert==6.4.5 types-cachetools==5.0.0 types-filelock==3.2.5 types-requests==2.27.16 -types-tabulate==0.8.6 +types-tabulate==0.8.7 # Extensions to datetime library types-python-dateutil==2.8.10 From f020d129d7ddf322398fded766f0fa967c1cf6cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 03:01:27 +0000 Subject: [PATCH 068/159] Bump types-python-dateutil from 2.8.10 to 2.8.11 Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.10 to 2.8.11. - [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 03bb5e72d..416d62e0d 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -28,4 +28,4 @@ types-requests==2.27.16 types-tabulate==0.8.6 # Extensions to datetime library -types-python-dateutil==2.8.10 +types-python-dateutil==2.8.11 From b69483e3afdd5438ced33aff2aec5baa7350a03d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 03:01:42 +0000 Subject: [PATCH 069/159] Bump nbconvert from 6.4.5 to 6.5.0 Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 6.4.5 to 6.5.0. - [Release notes](https://github.com/jupyter/nbconvert/releases) - [Commits](https://github.com/jupyter/nbconvert/compare/6.4.5...6.5) --- updated-dependencies: - dependency-name: nbconvert 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 03bb5e72d..43e9b01dd 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -19,7 +19,7 @@ isort==5.10.1 time-machine==2.6.0 # Convert jupyter notebooks to markdown documents -nbconvert==6.4.5 +nbconvert==6.5.0 # mypy types types-cachetools==5.0.0 From 153b31c9348ffa072126dfb4094962daf3317bfd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 06:11:57 +0000 Subject: [PATCH 070/159] Bump types-requests from 2.27.16 to 2.27.19 Bumps [types-requests](https://github.com/python/typeshed) from 2.27.16 to 2.27.19. - [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 70f5aaa3e..4fb4456f0 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,7 +24,7 @@ nbconvert==6.5.0 # mypy types types-cachetools==5.0.1 types-filelock==3.2.5 -types-requests==2.27.16 +types-requests==2.27.19 types-tabulate==0.8.7 # Extensions to datetime library From 1ce20ea739029a4825a4d7a4f5d0aad6c1a37dad Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 18 Apr 2022 08:16:38 +0200 Subject: [PATCH 071/159] Bump requirements to 1.79.81, min-required to 1.79.69 --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 07bb04be3..b225d7ff2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.22.3 pandas==1.4.2 pandas-ta==0.3.14b -ccxt==1.79.69 +ccxt==1.79.81 # Pin cryptography for now due to rust build errors with piwheels cryptography==36.0.2 aiohttp==3.8.1 diff --git a/setup.py b/setup.py index 640c8cc7b..250cafdc9 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ setup( ], install_requires=[ # from requirements.txt - 'ccxt>=1.77.29', + 'ccxt>=1.79.69', 'SQLAlchemy', 'python-telegram-bot>=13.4', 'arrow>=0.17.0', From 84f486295d806d4ae8347582f7d3d803bf41d256 Mon Sep 17 00:00:00 2001 From: froggleston Date: Tue, 19 Apr 2022 12:48:21 +0100 Subject: [PATCH 072/159] Add tests for new storing of backtest signal candles --- freqtrade/misc.py | 16 ++++++++++++++++ freqtrade/optimize/optimize_reports.py | 10 ++++------ tests/optimize/test_optimize_reports.py | 24 +++++++++++++++++++++++- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/freqtrade/misc.py b/freqtrade/misc.py index d5572ea0b..9087ec6e2 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -4,6 +4,7 @@ Various tool function for Freqtrade and scripts import gzip import hashlib import logging +import pickle import re from copy import deepcopy from datetime import datetime @@ -86,6 +87,21 @@ def file_dump_json(filename: Path, data: Any, is_zip: bool = False, log: bool = logger.debug(f'done json to "{filename}"') +def file_dump_pickle(filename: Path, data: Any, log: bool = True) -> None: + """ + Dump object data into a file + :param filename: file to create + :param data: Object data to save + :return: + """ + + if log: + logger.info(f'dumping pickle to "{filename}"') + with open(filename, 'wb') as fp: + pickle.dump(data, fp) + logger.debug(f'done pickling to "{filename}"') + + def json_load(datafile: IO) -> Any: """ load data with rapidjson diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index f0b2e2e71..ed29af839 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -1,5 +1,4 @@ import logging -import pickle from copy import deepcopy from datetime import datetime, timedelta, timezone from pathlib import Path @@ -12,8 +11,8 @@ from tabulate import tabulate from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT from freqtrade.data.btanalysis import (calculate_csum, calculate_market_change, calculate_max_drawdown) -from freqtrade.misc import (decimals_per_coin, file_dump_json, get_backtest_metadata_filename, - round_coin_value) +from freqtrade.misc import (decimals_per_coin, file_dump_json, file_dump_pickle, + get_backtest_metadata_filename, round_coin_value) logger = logging.getLogger(__name__) @@ -61,11 +60,10 @@ def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict] else: filename = Path.joinpath( recordfilename.parent, - f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}' + f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}_signals' ).with_suffix(recordfilename.suffix) - with open(filename, 'wb') as f: - pickle.dump(candles, f) + file_dump_pickle(filename, candles) def _get_line_floatfmt(stake_currency: str) -> List[str]: diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index 05c0bf575..a09620a71 100644 --- a/tests/optimize/test_optimize_reports.py +++ b/tests/optimize/test_optimize_reports.py @@ -1,5 +1,5 @@ import re -from datetime import timedelta +from datetime import timedelta, timezone from pathlib import Path import pandas as pd @@ -19,6 +19,7 @@ from freqtrade.optimize.optimize_reports import (_get_resample_from_period, gene generate_periodic_breakdown_stats, generate_strategy_comparison, generate_trading_stats, show_sorted_pairlist, + store_backtest_signal_candles, store_backtest_stats, text_table_bt_results, text_table_exit_reason, text_table_strategy) from freqtrade.resolvers.strategy_resolver import StrategyResolver @@ -201,6 +202,27 @@ def test_store_backtest_stats(testdatadir, mocker): assert str(dump_mock.call_args_list[0][0][0]).startswith(str(testdatadir / 'testresult')) +def test_store_backtest_candles(testdatadir, mocker): + + dump_mock = mocker.patch('freqtrade.optimize.optimize_reports.file_dump_pickle') + + # test directory exporting + store_backtest_signal_candles(testdatadir, {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}}) + + assert dump_mock.call_count == 1 + assert isinstance(dump_mock.call_args_list[0][0][0], Path) + assert str(dump_mock.call_args_list[0][0][0]).endswith(str('_signals.pkl')) + + dump_mock.reset_mock() + # test file exporting + filename = testdatadir / 'testresult' + store_backtest_signal_candles(filename, {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}}) + assert dump_mock.call_count == 1 + assert isinstance(dump_mock.call_args_list[0][0][0], Path) + # result will be testdatadir / testresult-_signals.pkl + assert str(dump_mock.call_args_list[0][0][0]).endswith(str('_signals.pkl')) + + def test_generate_pair_metrics(): results = pd.DataFrame( From aa5984930d3cb19b7fc2ed82b5590a6bad640d42 Mon Sep 17 00:00:00 2001 From: froggleston Date: Tue, 19 Apr 2022 13:00:09 +0100 Subject: [PATCH 073/159] Fix filename generation --- freqtrade/optimize/optimize_reports.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index ed29af839..05eec693e 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -60,8 +60,8 @@ def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict] else: filename = Path.joinpath( recordfilename.parent, - f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}_signals' - ).with_suffix(recordfilename.suffix) + f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}_signals.pkl' + ) file_dump_pickle(filename, candles) From 3ad1411f5ecba585be2a23972d412f692da15018 Mon Sep 17 00:00:00 2001 From: froggleston Date: Tue, 19 Apr 2022 13:08:01 +0100 Subject: [PATCH 074/159] Fix imports --- tests/optimize/test_optimize_reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index a09620a71..d72cf4e86 100644 --- a/tests/optimize/test_optimize_reports.py +++ b/tests/optimize/test_optimize_reports.py @@ -1,5 +1,5 @@ import re -from datetime import timedelta, timezone +from datetime import timedelta from pathlib import Path import pandas as pd From 9421d19cba64813a16094ff3bf2d332641e3fd89 Mon Sep 17 00:00:00 2001 From: froggleston Date: Tue, 19 Apr 2022 14:05:03 +0100 Subject: [PATCH 075/159] Add documentation --- docs/configuration.md | 7 +-- docs/strategy_analysis_example.md | 74 ++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 369c4e2dd..061b6c77c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -11,7 +11,7 @@ Per default, the bot loads the configuration from the `config.json` file, locate You can specify a different configuration file used by the bot with the `-c/--config` command-line option. -If you used the [Quick start](installation.md/#quick-start) method for installing +If you used the [Quick start](installation.md/#quick-start) method for installing the bot, the installation script should have already created the default configuration file (`config.json`) for you. If the default configuration file is not created we recommend to use `freqtrade new-config --config config.json` to generate a basic configuration file. @@ -64,7 +64,7 @@ This is similar to using multiple `--config` parameters, but simpler in usage as "config-private.json" ] ``` - + ``` bash freqtrade trade --config user_data/config.json <...> ``` @@ -100,7 +100,7 @@ This is similar to using multiple `--config` parameters, but simpler in usage as "stake_amount": "unlimited", } ``` - + Resulting combined configuration: ``` json title="Result" @@ -229,6 +229,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `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 +| `backtest_signal_candle_export_enable` | Enables the exporting of signal candles for use in post-backtesting analysis of buy tags. See [Strategy Analysis](strategy_analysis_example.md#analyse-the-buy-entry-and-sell-exit-tags).
*Defaults to `false`.*
**Datatype:** Boolean ### Parameters in the strategy diff --git a/docs/strategy_analysis_example.md b/docs/strategy_analysis_example.md index 2fa84a6df..48f54c824 100644 --- a/docs/strategy_analysis_example.md +++ b/docs/strategy_analysis_example.md @@ -93,7 +93,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" ``` @@ -250,3 +250,75 @@ fig.show() ``` Feel free to submit an issue or Pull Request enhancing this document if you would like to share ideas on how to best analyze the data. + +## Analyse the buy/entry and sell/exit tags + +It can be helpful to understand how a strategy behaves according to the buy/entry tags used to +mark up different buy conditions. You might want to see more complex statistics about each buy and +sell condition above those provided by the default backtesting output. You may also want to +determine indicator values on the signal candle that resulted in a trade opening. + +We first need to enable the exporting of trades from backtesting: + +``` +freqtrade backtesting -c --timeframe --strategy --timerange= --export=trades --export-filename=user_data/backtest_results/- +``` + +To analyse the buy tags, we need to use the buy_reasons.py script in the `scripts/` +folder. We need the signal candles for each opened trade so add the following option to your +config file: + +``` +'backtest_signal_candle_export_enable': true, +``` + +This will tell freqtrade to output a pickled dictionary of strategy, pairs and corresponding +DataFrame of the candles that resulted in buy signals. Depending on how many buys your strategy +makes, this file may get quite large, so periodically check your `user_data/backtest_results` +folder to delete old exports. + +Before running your next backtest, make sure you either delete your old backtest results or run +backtesting with the `--cache none` option to make sure no cached results are used. + +If all goes well, you should now see a `backtest-result-{timestamp}_signals.pkl` file in the +`user_data/backtest_results` folder. + +Now run the buy_reasons.py script, supplying a few options: + +``` +./scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 +``` + +The `-g` option is used to specify the various tabular outputs, ranging from the simplest (0) +to the most detailed per pair, per buy and per sell tag (4). More options are available by +running with the `-h` option. + +### Tuning the buy tags and sell tags to display + +To show only certain buy and sell tags in the displayed output, use the following two options: + +``` +--buy_reason_list : Comma separated list of buy signals to analyse. Default: "all" +--sell_reason_list : Comma separated list of sell signals to analyse. Default: "stop_loss,trailing_stop_loss" +``` + +For example: + +``` +./scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" +``` + +### Outputting signal candle indicators + +The real power of the buy_reasons.py script comes from the ability to print out the indicator +values present on signal candles to allow fine-grained investigation and tuning of buy signal +indicators. To print out a column for a given set of indicators, use the `--indicator-list` +option: + +``` +./scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" --indicator_list "rsi,rsi_1h,bb_lowerband,ema_9,macd,macdsignal" +``` + +The indicators have to be present in your strategy's main dataframe (either for your main +timeframe or for informatives) otherwise they will simply be ignored in the script +output. From b3cb7226467c359b0748cb4866f8f8fcfa649a53 Mon Sep 17 00:00:00 2001 From: froggleston Date: Wed, 20 Apr 2022 13:38:52 +0100 Subject: [PATCH 076/159] Use joblib instead of pickle, add signal candle read/write test, move docs to new Advanced Backtesting doc --- docs/advanced-backtesting.md | 75 +++++++++++++++++++++++++ docs/data-analysis.md | 1 + docs/strategy_analysis_example.md | 72 ------------------------ freqtrade/misc.py | 10 ++-- freqtrade/optimize/optimize_reports.py | 8 ++- tests/optimize/test_optimize_reports.py | 48 ++++++++++++++-- 6 files changed, 128 insertions(+), 86 deletions(-) create mode 100644 docs/advanced-backtesting.md diff --git a/docs/advanced-backtesting.md b/docs/advanced-backtesting.md new file mode 100644 index 000000000..9a7d71767 --- /dev/null +++ b/docs/advanced-backtesting.md @@ -0,0 +1,75 @@ +# Advanced Backtesting Analysis + +## Analyse the buy/entry and sell/exit tags + +It can be helpful to understand how a strategy behaves according to the buy/entry tags used to +mark up different buy conditions. You might want to see more complex statistics about each buy and +sell condition above those provided by the default backtesting output. You may also want to +determine indicator values on the signal candle that resulted in a trade opening. + +!!! Note + The following buy reason analysis is only available for backtesting, *not hyperopt*. + +We first need to enable the exporting of trades from backtesting: + +```bash +freqtrade backtesting -c --timeframe --strategy --timerange= --export=trades --export-filename=user_data/backtest_results/- +``` + +To analyse the buy tags, we need to use the `freqtrade tag-analysis` command. We need the signal +candles for each opened trade so add the following option to your config file: + +``` +'backtest_signal_candle_export_enable': true, +``` + +This will tell freqtrade to output a pickled dictionary of strategy, pairs and corresponding +DataFrame of the candles that resulted in buy signals. Depending on how many buys your strategy +makes, this file may get quite large, so periodically check your `user_data/backtest_results` +folder to delete old exports. + +Before running your next backtest, make sure you either delete your old backtest results or run +backtesting with the `--cache none` option to make sure no cached results are used. + +If all goes well, you should now see a `backtest-result-{timestamp}_signals.pkl` file in the +`user_data/backtest_results` folder. + +Now run the buy_reasons.py script, supplying a few options: + +```bash +freqtrade tag-analysis -c -s -t -g0,1,2,3,4 +``` + +The `-g` option is used to specify the various tabular outputs, ranging from the simplest (0) +to the most detailed per pair, per buy and per sell tag (4). More options are available by +running with the `-h` option. + +### Tuning the buy tags and sell tags to display + +To show only certain buy and sell tags in the displayed output, use the following two options: + +``` +--buy_reason_list : Comma separated list of buy signals to analyse. Default: "all" +--sell_reason_list : Comma separated list of sell signals to analyse. Default: "stop_loss,trailing_stop_loss" +``` + +For example: + +```bash +freqtrade tag-analysis -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" +``` + +### Outputting signal candle indicators + +The real power of the buy_reasons.py script comes from the ability to print out the indicator +values present on signal candles to allow fine-grained investigation and tuning of buy signal +indicators. To print out a column for a given set of indicators, use the `--indicator-list` +option: + +```bash +freqtrade tag-analysis -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" --indicator_list "rsi,rsi_1h,bb_lowerband,ema_9,macd,macdsignal" +``` + +The indicators have to be present in your strategy's main DataFrame (either for your main +timeframe or for informatives) otherwise they will simply be ignored in the script +output. diff --git a/docs/data-analysis.md b/docs/data-analysis.md index 9a79ee5ed..926ed3eae 100644 --- a/docs/data-analysis.md +++ b/docs/data-analysis.md @@ -122,5 +122,6 @@ Best avoid relative paths, since this starts at the storage location of the jupy * [Strategy debugging](strategy_analysis_example.md) - also available as Jupyter notebook (`user_data/notebooks/strategy_analysis_example.ipynb`) * [Plotting](plotting.md) +* [Tag Analysis](advanced-backtesting.md) Feel free to submit an issue or Pull Request enhancing this document if you would like to share ideas on how to best analyze the data. diff --git a/docs/strategy_analysis_example.md b/docs/strategy_analysis_example.md index 48f54c824..ae0c6a6a3 100644 --- a/docs/strategy_analysis_example.md +++ b/docs/strategy_analysis_example.md @@ -250,75 +250,3 @@ fig.show() ``` Feel free to submit an issue or Pull Request enhancing this document if you would like to share ideas on how to best analyze the data. - -## Analyse the buy/entry and sell/exit tags - -It can be helpful to understand how a strategy behaves according to the buy/entry tags used to -mark up different buy conditions. You might want to see more complex statistics about each buy and -sell condition above those provided by the default backtesting output. You may also want to -determine indicator values on the signal candle that resulted in a trade opening. - -We first need to enable the exporting of trades from backtesting: - -``` -freqtrade backtesting -c --timeframe --strategy --timerange= --export=trades --export-filename=user_data/backtest_results/- -``` - -To analyse the buy tags, we need to use the buy_reasons.py script in the `scripts/` -folder. We need the signal candles for each opened trade so add the following option to your -config file: - -``` -'backtest_signal_candle_export_enable': true, -``` - -This will tell freqtrade to output a pickled dictionary of strategy, pairs and corresponding -DataFrame of the candles that resulted in buy signals. Depending on how many buys your strategy -makes, this file may get quite large, so periodically check your `user_data/backtest_results` -folder to delete old exports. - -Before running your next backtest, make sure you either delete your old backtest results or run -backtesting with the `--cache none` option to make sure no cached results are used. - -If all goes well, you should now see a `backtest-result-{timestamp}_signals.pkl` file in the -`user_data/backtest_results` folder. - -Now run the buy_reasons.py script, supplying a few options: - -``` -./scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 -``` - -The `-g` option is used to specify the various tabular outputs, ranging from the simplest (0) -to the most detailed per pair, per buy and per sell tag (4). More options are available by -running with the `-h` option. - -### Tuning the buy tags and sell tags to display - -To show only certain buy and sell tags in the displayed output, use the following two options: - -``` ---buy_reason_list : Comma separated list of buy signals to analyse. Default: "all" ---sell_reason_list : Comma separated list of sell signals to analyse. Default: "stop_loss,trailing_stop_loss" -``` - -For example: - -``` -./scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" -``` - -### Outputting signal candle indicators - -The real power of the buy_reasons.py script comes from the ability to print out the indicator -values present on signal candles to allow fine-grained investigation and tuning of buy signal -indicators. To print out a column for a given set of indicators, use the `--indicator-list` -option: - -``` -./scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" --indicator_list "rsi,rsi_1h,bb_lowerband,ema_9,macd,macdsignal" -``` - -The indicators have to be present in your strategy's main dataframe (either for your main -timeframe or for informatives) otherwise they will simply be ignored in the script -output. diff --git a/freqtrade/misc.py b/freqtrade/misc.py index 9087ec6e2..be12d8224 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -4,7 +4,6 @@ Various tool function for Freqtrade and scripts import gzip import hashlib import logging -import pickle import re from copy import deepcopy from datetime import datetime @@ -13,6 +12,7 @@ from typing import Any, Iterator, List, Union from typing.io import IO from urllib.parse import urlparse +import joblib import rapidjson from freqtrade.constants import DECIMAL_PER_COIN_FALLBACK, DECIMALS_PER_COIN @@ -87,7 +87,7 @@ def file_dump_json(filename: Path, data: Any, is_zip: bool = False, log: bool = logger.debug(f'done json to "{filename}"') -def file_dump_pickle(filename: Path, data: Any, log: bool = True) -> None: +def file_dump_joblib(filename: Path, data: Any, log: bool = True) -> None: """ Dump object data into a file :param filename: file to create @@ -96,10 +96,10 @@ def file_dump_pickle(filename: Path, data: Any, log: bool = True) -> None: """ if log: - logger.info(f'dumping pickle to "{filename}"') + logger.info(f'dumping joblib to "{filename}"') with open(filename, 'wb') as fp: - pickle.dump(data, fp) - logger.debug(f'done pickling to "{filename}"') + joblib.dump(data, fp) + logger.debug(f'done joblib dump to "{filename}"') def json_load(datafile: IO) -> Any: diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 05eec693e..6288ee16a 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -11,7 +11,7 @@ from tabulate import tabulate from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT from freqtrade.data.btanalysis import (calculate_csum, calculate_market_change, calculate_max_drawdown) -from freqtrade.misc import (decimals_per_coin, file_dump_json, file_dump_pickle, +from freqtrade.misc import (decimals_per_coin, file_dump_joblib, file_dump_json, get_backtest_metadata_filename, round_coin_value) @@ -45,7 +45,7 @@ def store_backtest_stats(recordfilename: Path, stats: Dict[str, DataFrame]) -> N file_dump_json(latest_filename, {'latest_backtest': str(filename.name)}) -def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict]) -> None: +def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict]) -> Path: """ Stores backtest trade signal candles :param recordfilename: Path object, which can either be a filename or a directory. @@ -63,7 +63,9 @@ def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict] f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}_signals.pkl' ) - file_dump_pickle(filename, candles) + file_dump_joblib(filename, candles) + + return filename def _get_line_floatfmt(stake_currency: str) -> List[str]: diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index d72cf4e86..ff8d420b3 100644 --- a/tests/optimize/test_optimize_reports.py +++ b/tests/optimize/test_optimize_reports.py @@ -2,6 +2,7 @@ import re from datetime import timedelta from pathlib import Path +import joblib import pandas as pd import pytest from arrow import Arrow @@ -204,23 +205,58 @@ def test_store_backtest_stats(testdatadir, mocker): def test_store_backtest_candles(testdatadir, mocker): - dump_mock = mocker.patch('freqtrade.optimize.optimize_reports.file_dump_pickle') + dump_mock = mocker.patch('freqtrade.optimize.optimize_reports.file_dump_joblib') - # test directory exporting - store_backtest_signal_candles(testdatadir, {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}}) + candle_dict = {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}} + + # mock directory exporting + store_backtest_signal_candles(testdatadir, candle_dict) assert dump_mock.call_count == 1 assert isinstance(dump_mock.call_args_list[0][0][0], Path) assert str(dump_mock.call_args_list[0][0][0]).endswith(str('_signals.pkl')) dump_mock.reset_mock() - # test file exporting - filename = testdatadir / 'testresult' - store_backtest_signal_candles(filename, {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}}) + # mock file exporting + filename = Path(testdatadir / 'testresult') + store_backtest_signal_candles(filename, candle_dict) assert dump_mock.call_count == 1 assert isinstance(dump_mock.call_args_list[0][0][0], Path) # result will be testdatadir / testresult-_signals.pkl assert str(dump_mock.call_args_list[0][0][0]).endswith(str('_signals.pkl')) + dump_mock.reset_mock() + + +def test_write_read_backtest_candles(tmpdir): + + candle_dict = {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}} + + # test directory exporting + stored_file = store_backtest_signal_candles(Path(tmpdir), candle_dict) + scp = open(stored_file, "rb") + pickled_signal_candles = joblib.load(scp) + scp.close() + + assert pickled_signal_candles.keys() == candle_dict.keys() + assert pickled_signal_candles['DefStrat'].keys() == pickled_signal_candles['DefStrat'].keys() + assert pickled_signal_candles['DefStrat']['UNITTEST/BTC'] \ + .equals(pickled_signal_candles['DefStrat']['UNITTEST/BTC']) + + _clean_test_file(stored_file) + + # test file exporting + filename = Path(tmpdir / 'testresult') + stored_file = store_backtest_signal_candles(filename, candle_dict) + scp = open(stored_file, "rb") + pickled_signal_candles = joblib.load(scp) + scp.close() + + assert pickled_signal_candles.keys() == candle_dict.keys() + assert pickled_signal_candles['DefStrat'].keys() == pickled_signal_candles['DefStrat'].keys() + assert pickled_signal_candles['DefStrat']['UNITTEST/BTC'] \ + .equals(pickled_signal_candles['DefStrat']['UNITTEST/BTC']) + + _clean_test_file(stored_file) def test_generate_pair_metrics(): From ea7fb4e6e6182c71aabcaf0fea9bf52214644b90 Mon Sep 17 00:00:00 2001 From: froggleston Date: Wed, 20 Apr 2022 13:51:45 +0100 Subject: [PATCH 077/159] Revert docs to buy_reasons script version --- docs/advanced-backtesting.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/advanced-backtesting.md b/docs/advanced-backtesting.md index 9a7d71767..d8c6c505e 100644 --- a/docs/advanced-backtesting.md +++ b/docs/advanced-backtesting.md @@ -13,11 +13,15 @@ determine indicator values on the signal candle that resulted in a trade opening We first need to enable the exporting of trades from backtesting: ```bash -freqtrade backtesting -c --timeframe --strategy --timerange= --export=trades --export-filename=user_data/backtest_results/- +freqtrade backtesting -c --timeframe --strategy --timerange= --export=trades ``` -To analyse the buy tags, we need to use the `freqtrade tag-analysis` command. We need the signal -candles for each opened trade so add the following option to your config file: +To analyse the buy tags, we need to use the `buy_reasons.py` script from +[froggleston's repo](https://github.com/froggleston/freqtrade-buyreasons). Follow the instructions +in their README to copy the script into your `freqtrade/scripts/` folder. + +We then need the signal candles for each opened trade so add the following option to your +config file: ``` 'backtest_signal_candle_export_enable': true, @@ -37,7 +41,7 @@ If all goes well, you should now see a `backtest-result-{timestamp}_signals.pkl` Now run the buy_reasons.py script, supplying a few options: ```bash -freqtrade tag-analysis -c -s -t -g0,1,2,3,4 +python3 scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 ``` The `-g` option is used to specify the various tabular outputs, ranging from the simplest (0) @@ -56,7 +60,7 @@ To show only certain buy and sell tags in the displayed output, use the followin For example: ```bash -freqtrade tag-analysis -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" +python3 scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" ``` ### Outputting signal candle indicators @@ -67,7 +71,7 @@ indicators. To print out a column for a given set of indicators, use the `--indi option: ```bash -freqtrade tag-analysis -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" --indicator_list "rsi,rsi_1h,bb_lowerband,ema_9,macd,macdsignal" +python3 scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" --indicator_list "rsi,rsi_1h,bb_lowerband,ema_9,macd,macdsignal" ``` The indicators have to be present in your strategy's main DataFrame (either for your main From 933054a51ccb991a646452e2e26f2ea7cad37229 Mon Sep 17 00:00:00 2001 From: froggleston Date: Wed, 20 Apr 2022 13:54:50 +0100 Subject: [PATCH 078/159] Move enable option text to make better sense --- docs/advanced-backtesting.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/advanced-backtesting.md b/docs/advanced-backtesting.md index d8c6c505e..4d91c4305 100644 --- a/docs/advanced-backtesting.md +++ b/docs/advanced-backtesting.md @@ -10,7 +10,15 @@ determine indicator values on the signal candle that resulted in a trade opening !!! Note The following buy reason analysis is only available for backtesting, *not hyperopt*. -We first need to enable the exporting of trades from backtesting: +We first need to tell freqtrade to export the signal candles for each opened trade, +so add the following option to your config file: + +``` +'backtest_signal_candle_export_enable': true, +``` + +We then need to run backtesting and include the `--export` option to enable the exporting of +trades: ```bash freqtrade backtesting -c --timeframe --strategy --timerange= --export=trades @@ -20,13 +28,6 @@ To analyse the buy tags, we need to use the `buy_reasons.py` script from [froggleston's repo](https://github.com/froggleston/freqtrade-buyreasons). Follow the instructions in their README to copy the script into your `freqtrade/scripts/` folder. -We then need the signal candles for each opened trade so add the following option to your -config file: - -``` -'backtest_signal_candle_export_enable': true, -``` - This will tell freqtrade to output a pickled dictionary of strategy, pairs and corresponding DataFrame of the candles that resulted in buy signals. Depending on how many buys your strategy makes, this file may get quite large, so periodically check your `user_data/backtest_results` From f92997d3789c6eb8b9116e4a55dac2b9b7112aa7 Mon Sep 17 00:00:00 2001 From: froggleston Date: Wed, 20 Apr 2022 14:05:33 +0100 Subject: [PATCH 079/159] Move signal candle generation into separate function --- freqtrade/optimize/backtesting.py | 37 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 03a6cade0..9d7f19f7a 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -1079,26 +1079,29 @@ class Backtesting: if self.backtest_signal_candle_export_enable and \ self.dataprovider.runmode == RunMode.BACKTEST: - signal_candles_only = {} - for pair in preprocessed_tmp.keys(): - signal_candles_only_df = DataFrame() - - pairdf = preprocessed_tmp[pair] - resdf = results['results'] - pairresults = resdf.loc[(resdf["pair"] == pair)] - - if pairdf.shape[0] > 0: - for t, v in pairresults.open_date.items(): - allinds = pairdf.loc[(pairdf['date'] < v)] - signal_inds = allinds.iloc[[-1]] - signal_candles_only_df = signal_candles_only_df.append(signal_inds) - - signal_candles_only[pair] = signal_candles_only_df - - self.processed_dfs[self.strategy.get_strategy_name()] = signal_candles_only + self._generate_trade_signal_candles(preprocessed_tmp, results) return min_date, max_date + def _generate_trade_signal_candles(self, preprocessed_df, bt_results): + signal_candles_only = {} + for pair in preprocessed_df.keys(): + signal_candles_only_df = DataFrame() + + pairdf = preprocessed_df[pair] + resdf = bt_results['results'] + pairresults = resdf.loc[(resdf["pair"] == pair)] + + if pairdf.shape[0] > 0: + for t, v in pairresults.open_date.items(): + allinds = pairdf.loc[(pairdf['date'] < v)] + signal_inds = allinds.iloc[[-1]] + signal_candles_only_df = signal_candles_only_df.append(signal_inds) + + signal_candles_only[pair] = signal_candles_only_df + + self.processed_dfs[self.strategy.get_strategy_name()] = signal_candles_only + def _get_min_cached_backtest_date(self): min_backtest_date = None backtest_cache_age = self.config.get('backtest_cache', constants.BACKTEST_CACHE_DEFAULT) From ba305e93edb49defc42f9a8b01b957e33984722f Mon Sep 17 00:00:00 2001 From: Patel Kaushal <36811899+koradiyakaushal@users.noreply.github.com> Date: Thu, 21 Apr 2022 18:35:41 +0530 Subject: [PATCH 080/159] Ref: timeseries friendly merge_ordered in merge_informative_pair function --- freqtrade/strategy/strategy_helper.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/freqtrade/strategy/strategy_helper.py b/freqtrade/strategy/strategy_helper.py index a36cb3dbb..fef5fb812 100644 --- a/freqtrade/strategy/strategy_helper.py +++ b/freqtrade/strategy/strategy_helper.py @@ -56,12 +56,18 @@ def merge_informative_pair(dataframe: pd.DataFrame, informative: pd.DataFrame, # Combine the 2 dataframes # all indicators on the informative sample MUST be calculated before this point - dataframe = pd.merge(dataframe, informative, left_on='date', - right_on=date_merge, how='left') + if ffill: + # https://pandas.pydata.org/docs/user_guide/merging.html#timeseries-friendly-merging + # merge_ordered - ffill method is 2.5x faster than seperate ffill() + dataframe = pd.merge_ordered(dataframe, informative, fill_method="ffill", left_on='date', + right_on=date_merge, how='left') + else: + dataframe = pd.merge(dataframe, informative, left_on='date', + right_on=date_merge, how='left') dataframe = dataframe.drop(date_merge, axis=1) - if ffill: - dataframe = dataframe.ffill() + # if ffill: + # dataframe = dataframe.ffill() return dataframe From 7f60364f63057bba06dfc3bf3ed3886560906a3b Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 22 Apr 2022 06:38:51 +0200 Subject: [PATCH 081/159] Add doc-page to index --- docs/advanced-backtesting.md | 12 ++++++------ freqtrade/optimize/backtesting.py | 8 ++++---- mkdocs.yml | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/advanced-backtesting.md b/docs/advanced-backtesting.md index 4d91c4305..69dc428f1 100644 --- a/docs/advanced-backtesting.md +++ b/docs/advanced-backtesting.md @@ -1,6 +1,6 @@ # Advanced Backtesting Analysis -## Analyse the buy/entry and sell/exit tags +## Analyze the buy/entry and sell/exit tags It can be helpful to understand how a strategy behaves according to the buy/entry tags used to mark up different buy conditions. You might want to see more complex statistics about each buy and @@ -20,11 +20,11 @@ so add the following option to your config file: We then need to run backtesting and include the `--export` option to enable the exporting of trades: -```bash +``` bash freqtrade backtesting -c --timeframe --strategy --timerange= --export=trades ``` -To analyse the buy tags, we need to use the `buy_reasons.py` script from +To analyze the buy tags, we need to use the `buy_reasons.py` script from [froggleston's repo](https://github.com/froggleston/freqtrade-buyreasons). Follow the instructions in their README to copy the script into your `freqtrade/scripts/` folder. @@ -39,9 +39,9 @@ backtesting with the `--cache none` option to make sure no cached results are us If all goes well, you should now see a `backtest-result-{timestamp}_signals.pkl` file in the `user_data/backtest_results` folder. -Now run the buy_reasons.py script, supplying a few options: +Now run the `buy_reasons.py` script, supplying a few options: -```bash +``` bash python3 scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 ``` @@ -76,5 +76,5 @@ python3 scripts/buy_reasons.py -c -s -t Date: Fri, 22 Apr 2022 18:46:12 +0100 Subject: [PATCH 082/159] Add signals enum to 'export' cli option --- freqtrade/commands/arguments.py | 2 +- freqtrade/constants.py | 3 +-- freqtrade/optimize/backtesting.py | 5 +++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 7d4624bd1..8a108fe79 100644 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -23,7 +23,7 @@ ARGS_COMMON_OPTIMIZE = ["timeframe", "timerange", "dataformat_ohlcv", ARGS_BACKTEST = ARGS_COMMON_OPTIMIZE + ["position_stacking", "use_max_market_positions", "enable_protections", "dry_run_wallet", "timeframe_detail", - "strategy_list", "export", "exportfilename", + "strategy_list", "export", "exportfilename" "backtest_breakdown", "backtest_cache"] ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "hyperopt_path", diff --git a/freqtrade/constants.py b/freqtrade/constants.py index d21020a3f..1a21ec77f 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -14,7 +14,7 @@ PROCESS_THROTTLE_SECS = 5 # sec HYPEROPT_EPOCH = 100 # epochs RETRY_TIMEOUT = 30 # sec TIMEOUT_UNITS = ['minutes', 'seconds'] -EXPORT_OPTIONS = ['none', 'trades'] +EXPORT_OPTIONS = ['none', 'trades', 'signals'] DEFAULT_DB_PROD_URL = 'sqlite:///tradesv3.sqlite' DEFAULT_DB_DRYRUN_URL = 'sqlite:///tradesv3.dryrun.sqlite' UNLIMITED_STAKE_AMOUNT = 'unlimited' @@ -380,7 +380,6 @@ CONF_SCHEMA = { }, 'position_adjustment_enable': {'type': 'boolean'}, 'max_entry_position_adjustment': {'type': ['integer', 'number'], 'minimum': -1}, - 'backtest_signal_candle_export_enable': {'type': 'boolean'}, }, 'definitions': { 'exchange': { diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 9d7f19f7a..c2d9f1edb 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -1077,7 +1077,7 @@ class Backtesting: }) self.all_results[self.strategy.get_strategy_name()] = results - if self.backtest_signal_candle_export_enable and \ + if self.config.get('export', 'none') == 'signals' and \ self.dataprovider.runmode == RunMode.BACKTEST: self._generate_trade_signal_candles(preprocessed_tmp, results) @@ -1163,8 +1163,9 @@ class Backtesting: if self.config.get('export', 'none') == 'trades': store_backtest_stats(self.config['exportfilename'], self.results) - if self.backtest_signal_candle_export_enable and \ + if self.config.get('export', 'none') == 'signals' and \ self.dataprovider.runmode == RunMode.BACKTEST: + store_backtest_stats(self.config['exportfilename'], self.results) store_backtest_signal_candles(self.config['exportfilename'], self.processed_dfs) # Results may be mixed up now. Sort them so they follow --strategy-list order. From 2fc4e5e1172917368719fc82ec16e537298d55dc Mon Sep 17 00:00:00 2001 From: froggleston Date: Fri, 22 Apr 2022 18:54:02 +0100 Subject: [PATCH 083/159] Fix weird removal of comma --- freqtrade/commands/arguments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 8a108fe79..7d4624bd1 100644 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -23,7 +23,7 @@ ARGS_COMMON_OPTIMIZE = ["timeframe", "timerange", "dataformat_ohlcv", ARGS_BACKTEST = ARGS_COMMON_OPTIMIZE + ["position_stacking", "use_max_market_positions", "enable_protections", "dry_run_wallet", "timeframe_detail", - "strategy_list", "export", "exportfilename" + "strategy_list", "export", "exportfilename", "backtest_breakdown", "backtest_cache"] ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "hyperopt_path", From dff9d52b3067a843e48c57e56e70a3942611f88d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 08:51:52 +0200 Subject: [PATCH 084/159] Remove hints on no longer used option, add very primitive test --- docs/backtesting.md | 24 ++++++++++++------------ docs/configuration.md | 1 - freqtrade/optimize/backtesting.py | 11 ++++------- tests/optimize/test_backtesting.py | 5 ++++- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/docs/backtesting.md b/docs/backtesting.md index 5d836d01b..f732068f1 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -20,7 +20,8 @@ usage: freqtrade backtesting [-h] [-v] [--logfile FILE] [-V] [-c PATH] [--dry-run-wallet DRY_RUN_WALLET] [--timeframe-detail TIMEFRAME_DETAIL] [--strategy-list STRATEGY_LIST [STRATEGY_LIST ...]] - [--export {none,trades}] [--export-filename PATH] + [--export {none,trades,signals}] + [--export-filename PATH] [--breakdown {day,week,month} [{day,week,month} ...]] [--cache {none,day,week,month}] @@ -63,18 +64,17 @@ optional arguments: `30m`, `1h`, `1d`). --strategy-list STRATEGY_LIST [STRATEGY_LIST ...] Provide a space-separated list of strategies to - backtest. Please note that timeframe needs to be - set either in config or via command line. When using - this together with `--export trades`, the strategy- - name is injected into the filename (so `backtest- - data.json` becomes `backtest-data-SampleStrategy.json` - --export {none,trades} + backtest. Please note that timeframe needs to be set + either in config or via command line. When using this + together with `--export trades`, the strategy-name is + injected into the filename (so `backtest-data.json` + becomes `backtest-data-SampleStrategy.json` + --export {none,trades,signals} Export backtest results (default: trades). - --export-filename PATH - Save backtest results to the file with this filename. - Requires `--export` to be set as well. Example: - `--export-filename=user_data/backtest_results/backtest - _today.json` + --export-filename PATH, --backtest-filename PATH + Use this filename for backtest results.Requires + `--export` to be set as well. Example: `--export-filen + ame=user_data/backtest_results/backtest_today.json` --breakdown {day,week,month} [{day,week,month} ...] Show backtesting breakdown per [day, week, month]. --cache {none,day,week,month} diff --git a/docs/configuration.md b/docs/configuration.md index 061b6c77c..5770450a6 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -229,7 +229,6 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `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 -| `backtest_signal_candle_export_enable` | Enables the exporting of signal candles for use in post-backtesting analysis of buy tags. See [Strategy Analysis](strategy_analysis_example.md#analyse-the-buy-entry-and-sell-exit-tags).
*Defaults to `false`.*
**Datatype:** Boolean ### Parameters in the strategy diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index c2d9f1edb..f4149fdc1 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -131,9 +131,6 @@ class Backtesting: self.config['startup_candle_count'] = self.required_startup self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe) - self.backtest_signal_candle_export_enable = self.config.get( - 'backtest_signal_candle_export_enable', False) - self.trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT) # strategies which define "can_short=True" will fail to load in Spot mode. self._can_short = self.trading_mode != TradingMode.SPOT @@ -1077,8 +1074,8 @@ class Backtesting: }) self.all_results[self.strategy.get_strategy_name()] = results - if self.config.get('export', 'none') == 'signals' and \ - self.dataprovider.runmode == RunMode.BACKTEST: + if (self.config.get('export', 'none') == 'signals' and + self.dataprovider.runmode == RunMode.BACKTEST): self._generate_trade_signal_candles(preprocessed_tmp, results) return min_date, max_date @@ -1163,8 +1160,8 @@ class Backtesting: if self.config.get('export', 'none') == 'trades': store_backtest_stats(self.config['exportfilename'], self.results) - if self.config.get('export', 'none') == 'signals' and \ - self.dataprovider.runmode == RunMode.BACKTEST: + if (self.config.get('export', 'none') == 'signals' and + self.dataprovider.runmode == RunMode.BACKTEST): store_backtest_stats(self.config['exportfilename'], self.results) store_backtest_signal_candles(self.config['exportfilename'], self.processed_dfs) diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index 08957acf9..797d3bafa 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -384,14 +384,16 @@ def test_backtesting_start(default_conf, mocker, testdatadir, caplog) -> None: mocker.patch('freqtrade.optimize.backtesting.generate_backtest_stats') mocker.patch('freqtrade.optimize.backtesting.show_backtest_results') sbs = mocker.patch('freqtrade.optimize.backtesting.store_backtest_stats') + sbc = mocker.patch('freqtrade.optimize.backtesting.store_backtest_signal_candles') mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist', PropertyMock(return_value=['UNITTEST/BTC'])) default_conf['timeframe'] = '1m' default_conf['datadir'] = testdatadir - default_conf['export'] = 'trades' + default_conf['export'] = 'signals' default_conf['exportfilename'] = 'export.txt' default_conf['timerange'] = '-1510694220' + default_conf['runmode'] = RunMode.BACKTEST backtesting = Backtesting(default_conf) backtesting._set_strategy(backtesting.strategylist[0]) @@ -407,6 +409,7 @@ def test_backtesting_start(default_conf, mocker, testdatadir, caplog) -> None: assert backtesting.strategy.dp._pairlists is not None assert backtesting.strategy.bot_loop_start.call_count == 1 assert sbs.call_count == 1 + assert sbc.call_count == 1 def test_backtesting_start_no_data(default_conf, mocker, caplog, testdatadir) -> None: From c6927a1501d76b4e8b61ced9f5d1c53dbee75006 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 09:10:15 +0200 Subject: [PATCH 085/159] Fix argument spelling --- freqtrade/commands/arguments.py | 3 ++- freqtrade/commands/cli_options.py | 4 ++-- freqtrade/resolvers/iresolver.py | 9 ++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 2fb8d3258..e66f100c0 100644 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -37,7 +37,8 @@ ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "hyperopt_path", ARGS_EDGE = ARGS_COMMON_OPTIMIZE + ["stoploss_range"] -ARGS_LIST_STRATEGIES = ["strategy_path", "print_one_column", "print_colorized"] +ARGS_LIST_STRATEGIES = ["strategy_path", "print_one_column", "print_colorized", + "recursive_strategy_search"] ARGS_LIST_HYPEROPTS = ["hyperopt_path", "print_one_column", "print_colorized"] diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index 095aad6c3..548a7f473 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -83,9 +83,9 @@ AVAILABLE_CLI_OPTIONS = { action='store_true', ), "recursive_strategy_search": Arg( - '--recursive_strategy_search', + '--recursive-strategy-search', help='Recursively search for a strategy in the strategies folder.', - metavar='store_true', + action='store_true', ), # Main options "strategy": Arg( diff --git a/freqtrade/resolvers/iresolver.py b/freqtrade/resolvers/iresolver.py index cddc8b84d..d310856d8 100644 --- a/freqtrade/resolvers/iresolver.py +++ b/freqtrade/resolvers/iresolver.py @@ -44,7 +44,7 @@ class IResolver: @classmethod def build_search_paths(cls, config: Dict[str, Any], user_subdir: Optional[str] = None, - extra_dirs: Optional[List[str]] = None) -> List[Path]: + extra_dirs: List[str] = []) -> List[Path]: abs_paths: List[Path] = [] if cls.initial_search_path: @@ -53,10 +53,9 @@ class IResolver: if user_subdir: abs_paths.insert(0, config['user_data_dir'].joinpath(user_subdir)) - if extra_dirs: - # Add extra directory to the top of the search paths - for dir in extra_dirs: - abs_paths.insert(0, Path(dir).resolve()) + # Add extra directory to the top of the search paths + for dir in extra_dirs: + abs_paths.insert(0, Path(dir).resolve()) return abs_paths From ba92e09b7bab024fb7ea7a12d1b3df22cf33fc6a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 09:11:50 +0200 Subject: [PATCH 086/159] list-strategies should find recursively as well --- config_examples/config_full.example.json | 1 + freqtrade/commands/list_commands.py | 9 +++++---- freqtrade/optimize/hyperopt_tools.py | 3 ++- freqtrade/resolvers/iresolver.py | 11 +++++++++-- freqtrade/resolvers/strategy_resolver.py | 2 +- freqtrade/rpc/api_server/api_v1.py | 3 ++- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/config_examples/config_full.example.json b/config_examples/config_full.example.json index 7931476b4..8f14e1771 100644 --- a/config_examples/config_full.example.json +++ b/config_examples/config_full.example.json @@ -179,6 +179,7 @@ "disable_dataframe_checks": false, "strategy": "SampleStrategy", "strategy_path": "user_data/strategies/", + "recursive_strategy_search": false, "dataformat_ohlcv": "json", "dataformat_trades": "jsongz" } diff --git a/freqtrade/commands/list_commands.py b/freqtrade/commands/list_commands.py index 38fb098a0..1833db922 100644 --- a/freqtrade/commands/list_commands.py +++ b/freqtrade/commands/list_commands.py @@ -41,7 +41,7 @@ def start_list_exchanges(args: Dict[str, Any]) -> None: print(tabulate(exchanges, headers=['Exchange name', 'Valid', 'reason'])) -def _print_objs_tabular(objs: List, print_colorized: bool) -> None: +def _print_objs_tabular(objs: List, print_colorized: bool, base_dir: Path) -> None: if print_colorized: colorama_init(autoreset=True) red = Fore.RED @@ -55,7 +55,7 @@ def _print_objs_tabular(objs: List, print_colorized: bool) -> None: names = [s['name'] for s in objs] objs_to_print = [{ 'name': s['name'] if s['name'] else "--", - 'location': s['location'].name, + 'location': s['location'].relative_to(base_dir), 'status': (red + "LOAD FAILED" + reset if s['class'] is None else "OK" if names.count(s['name']) == 1 else yellow + "DUPLICATE NAME" + reset) @@ -77,7 +77,8 @@ def start_list_strategies(args: Dict[str, Any]) -> None: config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) directory = Path(config.get('strategy_path', config['user_data_dir'] / USERPATH_STRATEGIES)) - strategy_objs = StrategyResolver.search_all_objects(directory, not args['print_one_column']) + strategy_objs = StrategyResolver.search_all_objects( + directory, not args['print_one_column'], config.get('recursive_strategy_search', False)) # Sort alphabetically strategy_objs = sorted(strategy_objs, key=lambda x: x['name']) for obj in strategy_objs: @@ -89,7 +90,7 @@ def start_list_strategies(args: Dict[str, Any]) -> None: if args['print_one_column']: print('\n'.join([s['name'] for s in strategy_objs])) else: - _print_objs_tabular(strategy_objs, config.get('print_colorized', False)) + _print_objs_tabular(strategy_objs, config.get('print_colorized', False), directory) def start_list_timeframes(args: Dict[str, Any]) -> None: diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index 8c84f772a..e836681c5 100755 --- a/freqtrade/optimize/hyperopt_tools.py +++ b/freqtrade/optimize/hyperopt_tools.py @@ -41,7 +41,8 @@ class HyperoptTools(): """ from freqtrade.resolvers.strategy_resolver import StrategyResolver directory = Path(config.get('strategy_path', config['user_data_dir'] / USERPATH_STRATEGIES)) - strategy_objs = StrategyResolver.search_all_objects(directory, False) + strategy_objs = StrategyResolver.search_all_objects( + directory, False, config.get('recursive_strategy_search', False)) strategies = [s for s in strategy_objs if s['name'] == strategy_name] if strategies: strategy = strategies[0] diff --git a/freqtrade/resolvers/iresolver.py b/freqtrade/resolvers/iresolver.py index d310856d8..74b28dffe 100644 --- a/freqtrade/resolvers/iresolver.py +++ b/freqtrade/resolvers/iresolver.py @@ -182,18 +182,25 @@ class IResolver: ) @classmethod - def search_all_objects(cls, directory: Path, - enum_failed: bool) -> List[Dict[str, Any]]: + def search_all_objects(cls, directory: Path, enum_failed: bool, + recursive: bool = False) -> List[Dict[str, Any]]: """ Searches a directory for valid objects :param directory: Path to search :param enum_failed: If True, will return None for modules which fail. Otherwise, failing modules are skipped. + :param recursive: Recursively walk directory tree searching for strategies :return: List of dicts containing 'name', 'class' and 'location' entries """ logger.debug(f"Searching for {cls.object_type.__name__} '{directory}'") objects = [] for entry in directory.iterdir(): + if ( + recursive and entry.is_dir() + and not entry.name.startswith('__') + and not entry.name.startswith('.') + ): + objects.extend(cls.search_all_objects(entry, enum_failed, recursive=recursive)) # Only consider python files if entry.suffix != '.py': logger.debug('Ignoring %s', entry) diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index 8a22dbd65..60961b15b 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -167,7 +167,7 @@ class StrategyResolver(IResolver): :param extra_dir: additional directory to search for the given strategy :return: Strategy instance or None """ - if 'recursive_strategy_search' in config and config['recursive_strategy_search']: + if config.get('recursive_strategy_search', False): extra_dirs: List[str] = [ path[0] for path in walk(f"{config['user_data_dir']}/{USERPATH_STRATEGIES}") ] # sub-directories diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index 5a34385da..fe6426178 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -243,7 +243,8 @@ def list_strategies(config=Depends(get_config)): directory = Path(config.get( 'strategy_path', config['user_data_dir'] / USERPATH_STRATEGIES)) from freqtrade.resolvers.strategy_resolver import StrategyResolver - strategies = StrategyResolver.search_all_objects(directory, False) + strategies = StrategyResolver.search_all_objects( + directory, False, config.get('recursive_strategy_search', False)) strategies = sorted(strategies, key=lambda x: x['name']) return {'strategies': [x['name'] for x in strategies]} From aa5345190ec36bb20d03cc66c16c958c371b9214 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 09:19:18 +0200 Subject: [PATCH 087/159] Test recursive strategy-listing --- tests/commands/test_commands.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 1431bd22a..39294e568 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -892,6 +892,26 @@ def test_start_list_strategies(mocker, caplog, capsys): assert "legacy_strategy_v1.py" in captured.out assert CURRENT_TEST_STRATEGY in captured.out assert "LOAD FAILED" in captured.out + # Recursive + assert "TestStrategyNoImplements" not in captured.out + + # Test recursive + args = [ + "list-strategies", + "--strategy-path", + str(Path(__file__).parent.parent / "strategy" / "strats"), + '--no-color', + '--recursive-strategy-search' + ] + pargs = get_args(args) + # pargs['config'] = None + start_list_strategies(pargs) + captured = capsys.readouterr() + assert "TestStrategyLegacyV1" in captured.out + assert "legacy_strategy_v1.py" in captured.out + assert "StrategyTestV2" in captured.out + assert "TestStrategyNoImplements" in captured.out + assert "broken_strats/broken_futures_strategies.py" in captured.out def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys): From 580a2c6545ce79ffda7b54f2e1a928426d519aef Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 09:23:53 +0200 Subject: [PATCH 088/159] Don't repeat backtest-storing --- freqtrade/optimize/backtesting.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index f4149fdc1..f5571c4e2 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -1157,12 +1157,11 @@ class Backtesting: else: self.results = results - if self.config.get('export', 'none') == 'trades': + if self.config.get('export', 'none') in ('trades', 'signals'): store_backtest_stats(self.config['exportfilename'], self.results) if (self.config.get('export', 'none') == 'signals' and self.dataprovider.runmode == RunMode.BACKTEST): - store_backtest_stats(self.config['exportfilename'], self.results) store_backtest_signal_candles(self.config['exportfilename'], self.processed_dfs) # Results may be mixed up now. Sort them so they follow --strategy-list order. From 5a90d5ece67dc76866bb675fbe7a7f3f6ddbbaa2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 09:44:04 +0200 Subject: [PATCH 089/159] Fix docstring quotes --- freqtrade/optimize/hyperopt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index babcc5491..78d237c8d 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -410,7 +410,7 @@ class Hyperopt: dump(preprocessed, self.data_pickle_file) def get_asked_points(self, n_points: int) -> Tuple[List[List[Any]], List[bool]]: - ''' + """ Enforce points returned from `self.opt.ask` have not been already evaluated Steps: @@ -420,7 +420,7 @@ class Hyperopt: 4. If still some points are missing in respect to `n_points`, random sample some points 5. Repeat until at least `n_points` points in the `asked_non_tried` list 6. Return a list with length truncated at `n_points` - ''' + """ def unique_list(a_list): new_list = [] for item in a_list: From 30f314d580807bdb83969981293c162bdafc9a76 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 10:44:11 +0200 Subject: [PATCH 090/159] windows compatibility of test --- tests/commands/test_commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 39294e568..d1f54ad52 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -847,7 +847,7 @@ def test_start_convert_trades(mocker, caplog): assert convert_mock.call_count == 1 -def test_start_list_strategies(mocker, caplog, capsys): +def test_start_list_strategies(capsys): args = [ "list-strategies", @@ -911,7 +911,7 @@ def test_start_list_strategies(mocker, caplog, capsys): assert "legacy_strategy_v1.py" in captured.out assert "StrategyTestV2" in captured.out assert "TestStrategyNoImplements" in captured.out - assert "broken_strats/broken_futures_strategies.py" in captured.out + assert str(Path("broken_strats/broken_futures_strategies.py")) in captured.out def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys): From 84f5a4d5bc0e116ba1b7a5a476c9d4e717561cf3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 10:51:24 +0200 Subject: [PATCH 091/159] Fix indentation --- freqtrade/strategy/strategy_helper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/strategy/strategy_helper.py b/freqtrade/strategy/strategy_helper.py index fef5fb812..43728dc1f 100644 --- a/freqtrade/strategy/strategy_helper.py +++ b/freqtrade/strategy/strategy_helper.py @@ -60,10 +60,10 @@ def merge_informative_pair(dataframe: pd.DataFrame, informative: pd.DataFrame, # https://pandas.pydata.org/docs/user_guide/merging.html#timeseries-friendly-merging # merge_ordered - ffill method is 2.5x faster than seperate ffill() dataframe = pd.merge_ordered(dataframe, informative, fill_method="ffill", left_on='date', - right_on=date_merge, how='left') + right_on=date_merge, how='left') else: dataframe = pd.merge(dataframe, informative, left_on='date', - right_on=date_merge, how='left') + right_on=date_merge, how='left') dataframe = dataframe.drop(date_merge, axis=1) # if ffill: From 1120392f39f5e0f9fde546592e2a7e0b330f9e25 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 11:12:43 +0200 Subject: [PATCH 092/159] Fix pre-commit indentation --- .github/ISSUE_TEMPLATE/feature_request.md | 1 - .github/workflows/docker_update_readme.yml | 1 - .pre-commit-config.yaml | 34 +++++++++++++++++----- .pylintrc | 1 - docs/javascripts/config.js | 2 +- freqtrade.service | 1 - freqtrade.service.watchdog | 1 - requirements-plot.txt | 1 - 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index c32fb33c2..a18915462 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -24,4 +24,3 @@ Have you search for this feature before requesting it? It's highly likely that a ## Describe the enhancement *Explain the enhancement you would like* - diff --git a/.github/workflows/docker_update_readme.yml b/.github/workflows/docker_update_readme.yml index 822533ee2..4587626f6 100644 --- a/.github/workflows/docker_update_readme.yml +++ b/.github/workflows/docker_update_readme.yml @@ -15,4 +15,3 @@ jobs: DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} DOCKERHUB_REPOSITORY: freqtradeorg/freqtrade - diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 31af5b7c7..316baf0e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,21 +1,39 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: -- repo: https://github.com/pycqa/flake8 - rev: '4.0.1' + - repo: https://github.com/pycqa/flake8 + rev: "4.0.1" hooks: - - id: flake8 + - id: flake8 # stages: [push] -- repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v0.942' + - repo: https://github.com/pre-commit/mirrors-mypy + rev: "v0.942" hooks: - - id: mypy + - id: mypy # stages: [push] -- repo: https://github.com/pycqa/isort - rev: '5.10.1' + - repo: https://github.com/pycqa/isort + rev: "5.10.1" hooks: - id: isort name: isort (python) # stages: [push] + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.4.0 + hooks: + - id: end-of-file-fixer + exclude: | + (?x)^( + tests/.*| + .*\.svg + )$ + - id: mixed-line-ending + - id: debug-statements + - id: check-ast + - id: trailing-whitespace + exclude: | + (?x)^( + .*\.md + )$ diff --git a/.pylintrc b/.pylintrc index dce99c067..0932ecba4 100644 --- a/.pylintrc +++ b/.pylintrc @@ -7,4 +7,3 @@ ignore=vendor [TYPECHECK] ignored-modules=numpy,talib,talib.abstract - diff --git a/docs/javascripts/config.js b/docs/javascripts/config.js index 95d619efc..80e81ba59 100644 --- a/docs/javascripts/config.js +++ b/docs/javascripts/config.js @@ -9,4 +9,4 @@ window.MathJax = { ignoreHtmlClass: ".*|", processHtmlClass: "arithmatex" } -}; \ No newline at end of file +}; diff --git a/freqtrade.service b/freqtrade.service index df220ed39..6f0c73ee4 100644 --- a/freqtrade.service +++ b/freqtrade.service @@ -11,4 +11,3 @@ Restart=on-failure [Install] WantedBy=default.target - diff --git a/freqtrade.service.watchdog b/freqtrade.service.watchdog index 66ea00d76..dcd32ae18 100644 --- a/freqtrade.service.watchdog +++ b/freqtrade.service.watchdog @@ -27,4 +27,3 @@ WatchdogSec=20 [Install] WantedBy=default.target - diff --git a/requirements-plot.txt b/requirements-plot.txt index 9eb6a10a3..d9faed301 100644 --- a/requirements-plot.txt +++ b/requirements-plot.txt @@ -2,4 +2,3 @@ -r requirements.txt plotly==5.7.0 - From a2af7b4fd82ef5b1697aa427967a70cfff53f876 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 11:25:20 +0200 Subject: [PATCH 093/159] Test non-ffill approach --- tests/strategy/test_strategy_helpers.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/strategy/test_strategy_helpers.py b/tests/strategy/test_strategy_helpers.py index 65fb9f6dc..244fd3919 100644 --- a/tests/strategy/test_strategy_helpers.py +++ b/tests/strategy/test_strategy_helpers.py @@ -68,6 +68,21 @@ def test_merge_informative_pair(): assert result.iloc[7]['date_1h'] == result.iloc[4]['date'] assert result.iloc[8]['date_1h'] == result.iloc[4]['date'] + informative = generate_test_data('1h', 40) + result = merge_informative_pair(data, informative, '15m', '1h', ffill=False) + # First 3 rows are empty + assert result.iloc[0]['date_1h'] is pd.NaT + assert result.iloc[1]['date_1h'] is pd.NaT + assert result.iloc[2]['date_1h'] is pd.NaT + # Next 4 rows contain the starting date (0:00) + assert result.iloc[3]['date_1h'] == result.iloc[0]['date'] + assert result.iloc[4]['date_1h'] is pd.NaT + assert result.iloc[5]['date_1h'] is pd.NaT + assert result.iloc[6]['date_1h'] is pd.NaT + # Next 4 rows contain the next Hourly date original date row 4 + assert result.iloc[7]['date_1h'] == result.iloc[4]['date'] + assert result.iloc[8]['date_1h'] is pd.NaT + def test_merge_informative_pair_same(): data = generate_test_data('15m', 40) From f2912f88150e70256d163d904652862c4c398b8e Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 11:31:12 +0200 Subject: [PATCH 094/159] Improve mypy runs --- freqtrade/optimize/hyperopt.py | 6 +++--- freqtrade/optimize/optimize_reports.py | 2 +- setup.cfg | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 78d237c8d..3ae975ca7 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -290,7 +290,7 @@ class Hyperopt: self.assign_params(params_dict, 'protection') if HyperoptTools.has_space(self.config, 'roi'): - self.backtesting.strategy.minimal_roi = ( # type: ignore + self.backtesting.strategy.minimal_roi = ( self.custom_hyperopt.generate_roi_table(params_dict)) if HyperoptTools.has_space(self.config, 'stoploss'): @@ -465,8 +465,8 @@ class Hyperopt: # We don't need exchange instance anymore while running hyperopt self.backtesting.exchange.close() - self.backtesting.exchange._api = None # type: ignore - self.backtesting.exchange._api_async = None # type: ignore + self.backtesting.exchange._api = None + self.backtesting.exchange._api_async = None self.backtesting.exchange.loop = None # type: ignore # self.backtesting.exchange = None # type: ignore self.backtesting.pairlists = None # type: ignore diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 6288ee16a..0ceb3a411 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -264,7 +264,7 @@ def generate_edge_table(results: dict) -> str: # Ignore type as floatfmt does allow tuples but mypy does not know that return tabulate(tabular_data, headers=headers, - floatfmt=floatfmt, tablefmt="orgtbl", stralign="right") # type: ignore + floatfmt=floatfmt, tablefmt="orgtbl", stralign="right") def _get_resample_from_period(period: str) -> str: diff --git a/setup.cfg b/setup.cfg index f4a90bda7..a33ceda1f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -52,6 +52,7 @@ exclude = [mypy] ignore_missing_imports = True +warn_unused_ignores = True [mypy-tests.*] ignore_errors = True From c1a7fc873d5c447c1e985e17ba1773c24582f47c Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 11:47:10 +0200 Subject: [PATCH 095/159] Speed up ci by running coverage only where necessary --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8df7ab10..4e18127fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,6 +157,12 @@ jobs: pip install -e . - name: Tests + if: (runner.os != 'Linux' || matrix.python-version != '3.8') + run: | + pytest --random-order + + - name: Tests (with cov) + if: (runner.os == 'Linux' && matrix.python-version == '3.8') run: | pytest --random-order --cov=freqtrade --cov-config=.coveragerc From 3586c2e984845b95189cd2e0efc20fbe76425334 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 14:22:06 +0200 Subject: [PATCH 096/159] Windows no random order --- .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 4e18127fb..1902a6c45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -235,7 +235,7 @@ jobs: - name: Tests run: | - pytest --random-order --cov=freqtrade --cov-config=.coveragerc + pytest --random-order - name: Backtesting run: | From 12d03e6a91dbc2e383d071540455382d0ba953d4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 14:53:47 +0200 Subject: [PATCH 097/159] Remove unused test methods --- tests/conftest.py | 42 ---------------------------------------- tests/edge/test_edge.py | 43 ----------------------------------------- 2 files changed, 85 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index b1dcdbbd7..cc07de1de 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1632,40 +1632,6 @@ def limit_buy_order(limit_buy_order_open): return order -@pytest.fixture(scope='function') -def market_buy_order(): - return { - 'id': 'mocked_market_buy', - 'type': 'market', - 'side': 'buy', - 'symbol': 'mocked', - 'timestamp': arrow.utcnow().int_timestamp * 1000, - 'datetime': arrow.utcnow().isoformat(), - 'price': 0.00004099, - 'amount': 91.99181073, - 'filled': 91.99181073, - 'remaining': 0.0, - 'status': 'closed' - } - - -@pytest.fixture -def market_sell_order(): - return { - 'id': 'mocked_limit_sell', - 'type': 'market', - 'side': 'sell', - 'symbol': 'mocked', - 'timestamp': arrow.utcnow().int_timestamp * 1000, - 'datetime': arrow.utcnow().isoformat(), - 'price': 0.00004173, - 'amount': 91.99181073, - 'filled': 91.99181073, - 'remaining': 0.0, - 'status': 'closed' - } - - @pytest.fixture def limit_buy_order_old(): return { @@ -2946,14 +2912,6 @@ def limit_order(limit_buy_order_usdt, limit_sell_order_usdt): } -@pytest.fixture(scope='function') -def market_order(market_buy_order_usdt, market_sell_order_usdt): - return { - 'buy': market_buy_order_usdt, - 'sell': market_sell_order_usdt - } - - @pytest.fixture(scope='function') def limit_order_open(limit_buy_order_usdt_open, limit_sell_order_usdt_open): return { diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py index a43e82b22..aa7eefd27 100644 --- a/tests/edge/test_edge.py +++ b/tests/edge/test_edge.py @@ -30,49 +30,6 @@ from tests.optimize import (BTContainer, BTrade, _build_backtest_dataframe, tests_start_time = arrow.get(2018, 10, 3) timeframe_in_minute = 60 -# Helpers for this test file - - -def _validate_ohlc(buy_ohlc_sell_matrice): - for index, ohlc in enumerate(buy_ohlc_sell_matrice): - # if not high < open < low or not high < close < low - if not ohlc[3] >= ohlc[2] >= ohlc[4] or not ohlc[3] >= ohlc[5] >= ohlc[4]: - raise Exception('Line ' + str(index + 1) + ' of ohlc has invalid values!') - return True - - -def _build_dataframe(buy_ohlc_sell_matrice): - _validate_ohlc(buy_ohlc_sell_matrice) - data = [] - for ohlc in buy_ohlc_sell_matrice: - d = { - 'date': tests_start_time.shift( - minutes=( - ohlc[0] * - timeframe_in_minute)).int_timestamp * - 1000, - 'buy': ohlc[1], - 'open': ohlc[2], - 'high': ohlc[3], - 'low': ohlc[4], - 'close': ohlc[5], - 'sell': ohlc[6]} - data.append(d) - - frame = DataFrame(data) - frame['date'] = to_datetime(frame['date'], - unit='ms', - utc=True, - infer_datetime_format=True) - - return frame - - -def _time_on_candle(number): - return np.datetime64(tests_start_time.shift( - minutes=(number * timeframe_in_minute)).int_timestamp * 1000, 'ms') - - # End helper functions # Open trade should be removed from the end tc0 = BTContainer(data=[ From 0807d3106fea5c4d4f54050f64b8f808f6d4501c Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 15:34:40 +0200 Subject: [PATCH 098/159] Remove unused import --- tests/edge/test_edge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py index aa7eefd27..b30d6f998 100644 --- a/tests/edge/test_edge.py +++ b/tests/edge/test_edge.py @@ -8,7 +8,7 @@ from unittest.mock import MagicMock import arrow import numpy as np import pytest -from pandas import DataFrame, to_datetime +from pandas import DataFrame from freqtrade.data.converter import ohlcv_to_dataframe from freqtrade.edge import Edge, PairInfo From 2d07cbce597ed3e3053a3d31db0f8f87d35d4c68 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 17:05:41 +0200 Subject: [PATCH 099/159] Fix bad pre-commit installation closes #6713 --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index 5cde1a589..e0b010387 100755 --- a/setup.sh +++ b/setup.sh @@ -90,7 +90,7 @@ function updateenv() { echo "pip install completed" echo if [[ $dev =~ ^[Yy]$ ]]; then - ${PYTHON} -m pre-commit install + ${PYTHON} -m pre_commit install if [ $? -ne 0 ]; then echo "Failed installing pre-commit" exit 1 From 8cac0a47cca89bea4b69de00cbf54505679dcd24 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Apr 2022 17:08:34 +0200 Subject: [PATCH 100/159] Fix joblib being in wrong requirements --- environment.yml | 2 +- freqtrade/misc.py | 2 +- requirements-hyperopt.txt | 1 - requirements.txt | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/environment.yml b/environment.yml index f2f961894..19f3c7f5a 100644 --- a/environment.yml +++ b/environment.yml @@ -32,6 +32,7 @@ dependencies: - prompt-toolkit - schedule - python-dateutil + - joblib # ============================ @@ -54,7 +55,6 @@ dependencies: - scikit-learn - filelock - scikit-optimize - - joblib - progressbar2 # ============================ # 4/4 req plot diff --git a/freqtrade/misc.py b/freqtrade/misc.py index be12d8224..55a533725 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -12,7 +12,6 @@ from typing import Any, Iterator, List, Union from typing.io import IO from urllib.parse import urlparse -import joblib import rapidjson from freqtrade.constants import DECIMAL_PER_COIN_FALLBACK, DECIMALS_PER_COIN @@ -94,6 +93,7 @@ def file_dump_joblib(filename: Path, data: Any, log: bool = True) -> None: :param data: Object data to save :return: """ + import joblib if log: logger.info(f'dumping joblib to "{filename}"') diff --git a/requirements-hyperopt.txt b/requirements-hyperopt.txt index aeb7be035..32fc3f4b9 100644 --- a/requirements-hyperopt.txt +++ b/requirements-hyperopt.txt @@ -6,5 +6,4 @@ scipy==1.8.0 scikit-learn==1.0.2 scikit-optimize==0.9.0 filelock==3.6.0 -joblib==1.1.0 progressbar2==4.0.0 diff --git a/requirements.txt b/requirements.txt index 24f267b67..571d1892c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,6 +20,7 @@ pycoingecko==2.2.0 jinja2==3.1.1 tables==3.7.0 blosc==1.10.6 +joblib==1.1.0 # find first, C search in arrays py_find_1st==1.1.5 From acec5640143671600878c769d8d7dacc017c5434 Mon Sep 17 00:00:00 2001 From: froggleston Date: Sat, 23 Apr 2022 17:18:38 +0100 Subject: [PATCH 101/159] Update advanced backtesting docs to match fixed buy_reasons script --- docs/advanced-backtesting.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/advanced-backtesting.md b/docs/advanced-backtesting.md index 8a8c1af77..2a484da69 100644 --- a/docs/advanced-backtesting.md +++ b/docs/advanced-backtesting.md @@ -17,15 +17,15 @@ signals **and** trades: freqtrade backtesting -c --timeframe --strategy --timerange= --export=signals ``` -To analyze the buy tags, we need to use the `buy_reasons.py` script from -[froggleston's repo](https://github.com/froggleston/freqtrade-buyreasons). Follow the instructions -in their README to copy the script into your `freqtrade/scripts/` folder. - This will tell freqtrade to output a pickled dictionary of strategy, pairs and corresponding DataFrame of the candles that resulted in buy signals. Depending on how many buys your strategy makes, this file may get quite large, so periodically check your `user_data/backtest_results` folder to delete old exports. +To analyze the buy tags, we need to use the `buy_reasons.py` script from +[froggleston's repo](https://github.com/froggleston/freqtrade-buyreasons). Follow the instructions +in their README to copy the script into your `freqtrade/scripts/` folder. + Before running your next backtest, make sure you either delete your old backtest results or run backtesting with the `--cache none` option to make sure no cached results are used. @@ -47,14 +47,14 @@ running with the `-h` option. To show only certain buy and sell tags in the displayed output, use the following two options: ``` ---buy_reason_list : Comma separated list of buy signals to analyse. Default: "all" ---sell_reason_list : Comma separated list of sell signals to analyse. Default: "stop_loss,trailing_stop_loss" +--enter_reason_list : Comma separated list of enter signals to analyse. Default: "all" +--exit_reason_list : Comma separated list of exit signals to analyse. Default: "stop_loss,trailing_stop_loss" ``` For example: ```bash -python3 scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" +python3 scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --enter_reason_list "enter_tag_a,enter_tag_b" --exit_reason_list "roi,custom_exit_tag_a,stop_loss" ``` ### Outputting signal candle indicators @@ -65,7 +65,7 @@ indicators. To print out a column for a given set of indicators, use the `--indi option: ```bash -python3 scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --buy_reason_list "buy_tag_a,buy_tag_b" --sell_reason_list "roi,custom_sell_tag_a,stop_loss" --indicator_list "rsi,rsi_1h,bb_lowerband,ema_9,macd,macdsignal" +python3 scripts/buy_reasons.py -c -s -t -g0,1,2,3,4 --enter_reason_list "enter_tag_a,enter_tag_b" --exit_reason_list "roi,custom_exit_tag_a,stop_loss" --indicator_list "rsi,rsi_1h,bb_lowerband,ema_9,macd,macdsignal" ``` The indicators have to be present in your strategy's main DataFrame (either for your main From 3c17409bd71ab19823db3416a783d894b70886a3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 24 Apr 2022 14:28:15 +0200 Subject: [PATCH 102/159] Update buy to entry in backtesting --- freqtrade/optimize/backtesting.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index f5571c4e2..16f94e083 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -332,11 +332,11 @@ class Backtesting: self.dataprovider._set_cached_df( pair, self.timeframe, df_analyzed, self.config['candle_type_def']) - # Create a copy of the dataframe before shifting, that way the buy signal/tag + # Create a copy of the dataframe before shifting, that way the entry signal/tag # remains on the correct candle for callbacks. df_analyzed = df_analyzed.copy() - # To avoid using data from future, we use buy/sell signals shifted + # To avoid using data from future, we use entry/exit signals shifted # from the previous candle for col in headers[5:]: tag_col = col in ('enter_tag', 'exit_tag') @@ -649,7 +649,7 @@ class Backtesting: proposed_rate=propose_rate, entry_tag=entry_tag, side=direction, ) # default value is the open rate - # We can't place orders higher than current high (otherwise it'd be a stop limit buy) + # We can't place orders higher than current high (otherwise it'd be a stop limit entry) # which freqtrade does not support in live. if direction == "short": propose_rate = max(propose_rate, row[LOW_IDX]) @@ -813,7 +813,7 @@ class Backtesting: if len(open_trades[pair]) > 0: for trade in open_trades[pair]: if trade.open_order_id and trade.nr_of_successful_entries == 0: - # Ignore trade if buy-order did not fill yet + # Ignore trade if entry-order did not fill yet continue sell_row = data[pair][-1] @@ -869,7 +869,7 @@ class Backtesting: # Remove trade due to entry timeout expiration. return True else: - # Close additional buy order + # Close additional entry order del trade.orders[trade.orders.index(order)] if order.side == trade.exit_side: self.timedout_exit_orders += 1 @@ -882,7 +882,7 @@ class Backtesting: self, data: Dict, pair: str, row_index: int, current_time: datetime) -> Optional[Tuple]: try: # Row is treated as "current incomplete candle". - # Buy / sell signals are shifted by 1 to compensate for this. + # entry / exit signals are shifted by 1 to compensate for this. row = data[pair][row_index] except IndexError: # missing Data for one pair at the end. @@ -947,14 +947,14 @@ class Backtesting: self.dataprovider._set_dataframe_max_index(row_index) for t in list(open_trades[pair]): - # 1. Cancel expired buy/sell orders. + # 1. Cancel expired entry/exit orders. if self.check_order_cancel(t, current_time): - # Close trade due to buy timeout expiration. + # Close trade due to entry timeout expiration. open_trade_count -= 1 open_trades[pair].remove(t) self.wallets.update() - # 2. Process buys. + # 2. Process entries. # without positionstacking, we can only have one open trade per pair. # max_open_trades must be respected # don't open on the last row @@ -970,7 +970,7 @@ class Backtesting: if trade: # TODO: hacky workaround to avoid opening > max_open_trades # This emulates previous behavior - not sure if this is correct - # Prevents buying if the trade-slot was freed in this candle + # Prevents entering if the trade-slot was freed in this candle open_trade_count_start += 1 open_trade_count += 1 # logger.debug(f"{pair} - Emulate creation of new trade: {trade}.") @@ -1052,7 +1052,7 @@ class Backtesting: "No data left after adjusting for startup candles.") # Use preprocessed_tmp for date generation (the trimmed dataframe). - # Backtesting will re-trim the dataframes after buy/sell signal generation. + # Backtesting will re-trim the dataframes after entry/exit signal generation. min_date, max_date = history.get_timerange(preprocessed_tmp) logger.info(f'Backtesting with data from {min_date.strftime(DATETIME_PRINT_FORMAT)} ' f'up to {max_date.strftime(DATETIME_PRINT_FORMAT)} ' From 25c6c5e326a801556f4364d0dc5da95d6772b7af Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 24 Apr 2022 14:30:50 +0200 Subject: [PATCH 103/159] Update backtest sell terminology to exit --- freqtrade/optimize/backtesting.py | 92 +++++++++++++++--------------- tests/optimize/test_backtesting.py | 6 +- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 16f94e083..5442e425b 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -178,7 +178,7 @@ class Backtesting: # Attach Wallets to Strategy baseclass strategy.wallets = self.wallets # Set stoploss_on_exchange to false for backtesting, - # since a "perfect" stoploss-sell is assumed anyway + # since a "perfect" stoploss-exit is assumed anyway # And the regular "stoploss" function would not apply to that case self.strategy.order_types['stoploss_on_exchange'] = False @@ -353,24 +353,24 @@ class Backtesting: data[pair] = df_analyzed[headers].values.tolist() if not df_analyzed.empty else [] return data - def _get_close_rate(self, row: Tuple, trade: LocalTrade, sell: ExitCheckTuple, + def _get_close_rate(self, row: Tuple, trade: LocalTrade, exit: ExitCheckTuple, trade_dur: int) -> float: """ Get close rate for backtesting result """ # Special handling if high or low hit STOP_LOSS or ROI - if sell.exit_type in (ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS): - return self._get_close_rate_for_stoploss(row, trade, sell, trade_dur) - elif sell.exit_type == (ExitType.ROI): - return self._get_close_rate_for_roi(row, trade, sell, trade_dur) + if exit.exit_type in (ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS): + 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) else: return row[OPEN_IDX] - def _get_close_rate_for_stoploss(self, row: Tuple, trade: LocalTrade, sell: ExitCheckTuple, + def _get_close_rate_for_stoploss(self, row: Tuple, trade: LocalTrade, exit: ExitCheckTuple, trade_dur: int) -> float: # our stoploss was already lower than candle high, # possibly due to a cancelled trade exit. - # sell at open price. + # exit at open price. is_short = trade.is_short or False leverage = trade.leverage or 1.0 side_1 = -1 if is_short else 1 @@ -384,7 +384,7 @@ class Backtesting: # Special case: trailing triggers within same candle as trade opened. Assume most # pessimistic price movement, which is moving just enough to arm stoploss and # immediately going down to stop price. - if sell.exit_type == ExitType.TRAILING_STOP_LOSS and trade_dur == 0: + if exit.exit_type == ExitType.TRAILING_STOP_LOSS and trade_dur == 0: if ( not self.strategy.use_custom_stoploss and self.strategy.trailing_stop and self.strategy.trailing_only_offset_is_reached @@ -403,7 +403,7 @@ class Backtesting: else: assert stop_rate < row[HIGH_IDX] - # Limit lower-end to candle low to avoid sells below the low. + # Limit lower-end to candle low to avoid exits below the low. # This still remains "worst case" - but "worst realistic case". if is_short: return min(row[HIGH_IDX], stop_rate) @@ -413,7 +413,7 @@ class Backtesting: # Set close_rate to stoploss return trade.stop_loss - def _get_close_rate_for_roi(self, row: Tuple, trade: LocalTrade, sell: ExitCheckTuple, + def _get_close_rate_for_roi(self, row: Tuple, trade: LocalTrade, exit: ExitCheckTuple, trade_dur: int) -> float: is_short = trade.is_short or False leverage = trade.leverage or 1.0 @@ -438,7 +438,7 @@ class Backtesting: and roi_entry % self.timeframe_min == 0 and is_new_roi): # new ROI entry came into effect. - # use Open rate if open_rate > calculated sell rate + # use Open rate if open_rate > calculated exit rate return row[OPEN_IDX] if (trade_dur == 0 and ( @@ -461,11 +461,11 @@ class Backtesting: # ROI on opening candles with custom pricing can only # trigger if the entry was at Open or lower wick. # details: https: // github.com/freqtrade/freqtrade/issues/6261 - # If open_rate is < open, only allow sells below the close on red candles. + # If open_rate is < open, only allow exits below the close on red candles. raise ValueError("Opening candle ROI on red candles.") # Use the maximum between close_rate and low as we - # cannot sell outside of a candle. + # cannot exit outside of a candle. # Applies when a new ROI setting comes in place and the whole candle is above that. return min(max(close_rate, row[LOW_IDX]), row[HIGH_IDX]) @@ -500,7 +500,7 @@ class Backtesting: """ Rate is within candle, therefore filled""" return row[LOW_IDX] <= rate <= row[HIGH_IDX] - def _get_sell_trade_entry_for_candle(self, trade: LocalTrade, + def _get_exit_trade_entry_for_candle(self, trade: LocalTrade, row: Tuple) -> Optional[LocalTrade]: # Check if we need to adjust our current positions @@ -512,33 +512,33 @@ class Backtesting: if check_adjust_entry: trade = self._get_adjust_trade_entry_for_candle(trade, row) - sell_candle_time: datetime = row[DATE_IDX].to_pydatetime() + exit_candle_time: datetime = row[DATE_IDX].to_pydatetime() enter = row[SHORT_IDX] if trade.is_short else row[LONG_IDX] exit_ = row[ESHORT_IDX] if trade.is_short else row[ELONG_IDX] - sell = self.strategy.should_exit( - trade, row[OPEN_IDX], sell_candle_time, # type: ignore + exit_ = self.strategy.should_exit( + trade, row[OPEN_IDX], exit_candle_time, # type: ignore enter=enter, exit_=exit_, low=row[LOW_IDX], high=row[HIGH_IDX] ) - if sell.exit_flag: - trade.close_date = sell_candle_time + if exit_.exit_flag: + trade.close_date = exit_candle_time trade_dur = int((trade.close_date_utc - trade.open_date_utc).total_seconds() // 60) try: - closerate = self._get_close_rate(row, trade, sell, trade_dur) + closerate = self._get_close_rate(row, trade, exit_, trade_dur) except ValueError: return None # call the custom exit price,with default value as previous closerate current_profit = trade.calc_profit_ratio(closerate) order_type = self.strategy.order_types['exit'] - if sell.exit_type in (ExitType.EXIT_SIGNAL, ExitType.CUSTOM_EXIT): - # Custom exit pricing only for sell-signals + if exit_.exit_type in (ExitType.EXIT_SIGNAL, ExitType.CUSTOM_EXIT): + # Custom exit pricing only for exit-signals if order_type == 'limit': closerate = strategy_safe_wrapper(self.strategy.custom_exit_price, default_retval=closerate)( pair=trade.pair, trade=trade, - current_time=sell_candle_time, + current_time=exit_candle_time, proposed_rate=closerate, current_profit=current_profit) # We can't place orders lower than current low. # freqtrade does not support this in live, and the order would fill immediately @@ -553,12 +553,12 @@ class Backtesting: pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, rate=closerate, time_in_force=time_in_force, - sell_reason=sell.exit_reason, # deprecated - exit_reason=sell.exit_reason, - current_time=sell_candle_time): + sell_reason=exit_.exit_reason, # deprecated + exit_reason=exit_.exit_reason, + current_time=exit_candle_time): return None - trade.exit_reason = sell.exit_reason + trade.exit_reason = exit_.exit_reason # Checks and adds an exit tag, after checking that the length of the # row has the length for an exit tag column @@ -573,8 +573,8 @@ class Backtesting: order = Order( id=self.order_id_counter, ft_trade_id=trade.id, - order_date=sell_candle_time, - order_update_date=sell_candle_time, + 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), @@ -595,8 +595,8 @@ class Backtesting: return None - def _get_sell_trade_entry(self, trade: LocalTrade, row: Tuple) -> Optional[LocalTrade]: - sell_candle_time: datetime = row[DATE_IDX].to_pydatetime() + def _get_exit_trade_entry(self, trade: LocalTrade, row: Tuple) -> Optional[LocalTrade]: + exit_candle_time: datetime = row[DATE_IDX].to_pydatetime() if self.trading_mode == TradingMode.FUTURES: trade.funding_fees = self.exchange.calculate_funding_fees( @@ -604,20 +604,20 @@ class Backtesting: amount=trade.amount, is_short=trade.is_short, open_date=trade.open_date_utc, - close_date=sell_candle_time, + close_date=exit_candle_time, ) if self.timeframe_detail and trade.pair in self.detail_data: - sell_candle_end = sell_candle_time + timedelta(minutes=self.timeframe_min) + exit_candle_end = exit_candle_time + timedelta(minutes=self.timeframe_min) detail_data = self.detail_data[trade.pair] detail_data = detail_data.loc[ - (detail_data['date'] >= sell_candle_time) & - (detail_data['date'] < sell_candle_end) + (detail_data['date'] >= exit_candle_time) & + (detail_data['date'] < exit_candle_end) ].copy() if len(detail_data) == 0: # Fall back to "regular" data if no detail data was found for this candle - return self._get_sell_trade_entry_for_candle(trade, row) + return self._get_exit_trade_entry_for_candle(trade, row) detail_data.loc[:, 'enter_long'] = row[LONG_IDX] detail_data.loc[:, 'exit_long'] = row[ELONG_IDX] detail_data.loc[:, 'enter_short'] = row[SHORT_IDX] @@ -627,14 +627,14 @@ class Backtesting: headers = ['date', 'open', 'high', 'low', 'close', 'enter_long', 'exit_long', 'enter_short', 'exit_short', 'enter_tag', 'exit_tag'] for det_row in detail_data[headers].values.tolist(): - res = self._get_sell_trade_entry_for_candle(trade, det_row) + res = self._get_exit_trade_entry_for_candle(trade, det_row) if res: return res return None else: - return self._get_sell_trade_entry_for_candle(trade, row) + return self._get_exit_trade_entry_for_candle(trade, row) def get_valid_price_and_stake( self, pair: str, row: Tuple, propose_rate: float, stake_amount: Optional[float], @@ -815,11 +815,11 @@ class Backtesting: if trade.open_order_id and trade.nr_of_successful_entries == 0: # Ignore trade if entry-order did not fill yet continue - sell_row = data[pair][-1] + exit_row = data[pair][-1] - trade.close_date = sell_row[DATE_IDX].to_pydatetime() + trade.close_date = exit_row[DATE_IDX].to_pydatetime() trade.exit_reason = ExitType.FORCE_EXIT.value - trade.close(sell_row[OPEN_IDX], show_msg=False) + trade.close(exit_row[OPEN_IDX], show_msg=False) LocalTrade.close_bt_trade(trade) # Deepcopy object to have wallets update correctly trade1 = deepcopy(trade) @@ -985,18 +985,18 @@ class Backtesting: LocalTrade.add_bt_trade(trade) self.wallets.update() - # 4. Create sell orders (if any) + # 4. Create exit orders (if any) if not trade.open_order_id: - self._get_sell_trade_entry(trade, row) # Place sell order if necessary + self._get_exit_trade_entry(trade, row) # Place exit order if necessary - # 5. Process sell orders. + # 5. Process exit orders. order = trade.select_order(trade.exit_side, is_open=True) if order and self._get_order_filled(order.price, row): trade.open_order_id = None trade.close_date = current_time trade.close(order.price, show_msg=False) - # logger.debug(f"{pair} - Backtesting sell {trade}") + # logger.debug(f"{pair} - Backtesting exit {trade}") open_trade_count -= 1 open_trades[pair].remove(trade) LocalTrade.close_bt_trade(trade) diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index 797d3bafa..4d32a7516 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -714,7 +714,7 @@ def test_backtest__get_sell_trade_entry(default_conf, fee, mocker) -> None: ) # No data available. - res = backtesting._get_sell_trade_entry(trade, row_sell) + res = backtesting._get_exit_trade_entry(trade, row_sell) assert res is not None assert res.exit_reason == ExitType.ROI.value assert res.close_date_utc == datetime(2020, 1, 1, 5, 0, tzinfo=timezone.utc) @@ -727,13 +727,13 @@ def test_backtest__get_sell_trade_entry(default_conf, fee, mocker) -> None: [], columns=['date', 'open', 'high', 'low', 'close', 'enter_long', 'exit_long', 'enter_short', 'exit_short', 'long_tag', 'short_tag', 'exit_tag']) - res = backtesting._get_sell_trade_entry(trade, row) + res = backtesting._get_exit_trade_entry(trade, row) assert res is None # Assign backtest-detail data backtesting.detail_data[pair] = row_detail - res = backtesting._get_sell_trade_entry(trade, row_sell) + res = backtesting._get_exit_trade_entry(trade, row_sell) assert res is not None assert res.exit_reason == ExitType.ROI.value # Sell at minute 3 (not available above!) From 46ac46a5d3a9629b7f9d3ce8c704f693336b811f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 03:17:23 +0000 Subject: [PATCH 104/159] Bump ccxt from 1.79.81 to 1.80.61 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.79.81 to 1.80.61. - [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.79.81...1.80.61) --- 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 571d1892c..de14b9f2c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.22.3 pandas==1.4.2 pandas-ta==0.3.14b -ccxt==1.79.81 +ccxt==1.80.61 # Pin cryptography for now due to rust build errors with piwheels cryptography==36.0.2 aiohttp==3.8.1 From 5bfa2186a77f774cb3043edabafd56745dab3a53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 03:17:29 +0000 Subject: [PATCH 105/159] Bump pytest from 7.1.1 to 7.1.2 Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.1 to 7.1.2. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.1.1...7.1.2) --- updated-dependencies: - dependency-name: pytest 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 4fb4456f0..7f914875b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -9,7 +9,7 @@ flake8==4.0.1 flake8-tidy-imports==4.6.0 mypy==0.942 pre-commit==2.18.1 -pytest==7.1.1 +pytest==7.1.2 pytest-asyncio==0.18.3 pytest-cov==3.0.0 pytest-mock==3.7.0 From eee9fbb6690fa23749a4cf71940ec2e83bcb59c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 03:17:38 +0000 Subject: [PATCH 106/159] Bump types-python-dateutil from 2.8.11 to 2.8.12 Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.11 to 2.8.12. - [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 4fb4456f0..4f296b321 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -28,4 +28,4 @@ types-requests==2.27.19 types-tabulate==0.8.7 # Extensions to datetime library -types-python-dateutil==2.8.11 +types-python-dateutil==2.8.12 From 9b39c835867120a69041c36712700a45eab49694 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 03:17:44 +0000 Subject: [PATCH 107/159] Bump mkdocs-material from 8.2.9 to 8.2.10 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.2.9 to 8.2.10. - [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.2.9...8.2.10) --- 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 8d03a38c3..c6b683e8f 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,5 @@ mkdocs==1.3.0 -mkdocs-material==8.2.9 +mkdocs-material==8.2.10 mdx_truly_sane_lists==1.2 pymdown-extensions==9.3 jinja2==3.1.1 From 399be6f4e54566cf4e8e7d5d2f4719c9d0a9a765 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 03:17:53 +0000 Subject: [PATCH 108/159] Bump types-requests from 2.27.19 to 2.27.20 Bumps [types-requests](https://github.com/python/typeshed) from 2.27.19 to 2.27.20. - [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 4fb4456f0..be23d14bf 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,7 +24,7 @@ nbconvert==6.5.0 # mypy types types-cachetools==5.0.1 types-filelock==3.2.5 -types-requests==2.27.19 +types-requests==2.27.20 types-tabulate==0.8.7 # Extensions to datetime library From b4afbb0b0ac2bdb96a6b653bc44240c3e5669112 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 04:54:53 +0000 Subject: [PATCH 109/159] Bump pymdown-extensions from 9.3 to 9.4 Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 9.3 to 9.4. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/9.3...9.4) --- updated-dependencies: - dependency-name: pymdown-extensions 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 c6b683e8f..97be17243 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,5 @@ mkdocs==1.3.0 mkdocs-material==8.2.10 mdx_truly_sane_lists==1.2 -pymdown-extensions==9.3 +pymdown-extensions==9.4 jinja2==3.1.1 From 562e36c3ec20ce5d05c44fac78eb7e2ac71fb7a8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 07:01:27 +0200 Subject: [PATCH 110/159] Remove Interface V1 support --- freqtrade/resolvers/strategy_resolver.py | 18 +++++++++------ freqtrade/strategy/interface.py | 28 ++++-------------------- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index 0265ad6c3..44d590b67 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -217,15 +217,19 @@ class StrategyResolver(IResolver): raise OperationalException( "`populate_exit_trend` or `populate_sell_trend` must be implemented.") - strategy._populate_fun_len = len(getfullargspec(strategy.populate_indicators).args) - strategy._buy_fun_len = len(getfullargspec(strategy.populate_buy_trend).args) - strategy._sell_fun_len = len(getfullargspec(strategy.populate_sell_trend).args) + _populate_fun_len = len(getfullargspec(strategy.populate_indicators).args) + _buy_fun_len = len(getfullargspec(strategy.populate_buy_trend).args) + _sell_fun_len = len(getfullargspec(strategy.populate_sell_trend).args) if any(x == 2 for x in [ - strategy._populate_fun_len, - strategy._buy_fun_len, - strategy._sell_fun_len + _populate_fun_len, + _buy_fun_len, + _sell_fun_len ]): - strategy.INTERFACE_VERSION = 1 + raise OperationalException( + "Strategy Interface v1 is no longer supported. " + "Please update your strategy to implement " + "`populate_indicators`, `populate_entry_trend` and `populate_exit_trend` " + "with the metadata argument. ") return strategy @staticmethod diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index afcc1aa99..0ec3895bc 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -3,7 +3,6 @@ IStrategy interface This module defines the interface to apply for strategies """ import logging -import warnings from abc import ABC, abstractmethod from datetime import datetime, timedelta, timezone from typing import Dict, List, Optional, Tuple, Union @@ -44,14 +43,11 @@ class IStrategy(ABC, HyperStrategyMixin): """ # Strategy interface version # Default to version 2 - # Version 1 is the initial interface without metadata dict + # Version 1 is the initial interface without metadata dict - deprecated and no longer supported. # Version 2 populate_* include metadata dict # Version 3 - First version with short and leverage support INTERFACE_VERSION: int = 3 - _populate_fun_len: int = 0 - _buy_fun_len: int = 0 - _sell_fun_len: int = 0 _ft_params_from_file: Dict # associated minimal roi minimal_roi: Dict = {} @@ -1090,12 +1086,7 @@ class IStrategy(ABC, HyperStrategyMixin): dataframe = _create_and_merge_informative_pair( self, dataframe, metadata, inf_data, populate_fn) - if self._populate_fun_len == 2: - warnings.warn("deprecated - check out the Sample strategy to see " - "the current function headers!", DeprecationWarning) - return self.populate_indicators(dataframe) # type: ignore - else: - return self.populate_indicators(dataframe, metadata) + return self.populate_indicators(dataframe, metadata) def advise_entry(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ @@ -1109,12 +1100,7 @@ class IStrategy(ABC, HyperStrategyMixin): logger.debug(f"Populating enter signals for pair {metadata.get('pair')}.") - if self._buy_fun_len == 2: - warnings.warn("deprecated - check out the Sample strategy to see " - "the current function headers!", DeprecationWarning) - df = self.populate_buy_trend(dataframe) # type: ignore - else: - df = self.populate_entry_trend(dataframe, metadata) + df = self.populate_entry_trend(dataframe, metadata) if 'enter_long' not in df.columns: df = df.rename({'buy': 'enter_long', 'buy_tag': 'enter_tag'}, axis='columns') @@ -1129,14 +1115,8 @@ class IStrategy(ABC, HyperStrategyMixin): currently traded pair :return: DataFrame with exit column """ - logger.debug(f"Populating exit signals for pair {metadata.get('pair')}.") - if self._sell_fun_len == 2: - warnings.warn("deprecated - check out the Sample strategy to see " - "the current function headers!", DeprecationWarning) - df = self.populate_sell_trend(dataframe) # type: ignore - else: - df = self.populate_exit_trend(dataframe, metadata) + df = self.populate_exit_trend(dataframe, metadata) if 'exit_long' not in df.columns: df = df.rename({'sell': 'exit_long'}, axis='columns') return df From ec2582a4aed614dd1da552e9b76562e09f41c3d8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 07:02:09 +0200 Subject: [PATCH 111/159] Update tests to no longer use Strategy V1 --- tests/optimize/test_backtesting.py | 27 ++++----- tests/strategy/strats/legacy_strategy_v1.py | 60 +----------------- tests/strategy/test_interface.py | 2 +- tests/strategy/test_strategy_loading.py | 67 ++------------------- 4 files changed, 21 insertions(+), 135 deletions(-) diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index 4d32a7516..d7ee4a042 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -500,7 +500,7 @@ def test_backtesting_pairlist_list(default_conf, mocker, caplog, testdatadir, ti Backtesting(default_conf) # Multiple strategies - default_conf['strategy_list'] = [CURRENT_TEST_STRATEGY, 'TestStrategyLegacyV1'] + default_conf['strategy_list'] = [CURRENT_TEST_STRATEGY, 'StrategyTestV2'] with pytest.raises(OperationalException, match='PrecisionFilter not allowed for backtesting multiple strategies.'): Backtesting(default_conf) @@ -1198,7 +1198,7 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir): '--disable-max-market-positions', '--strategy-list', CURRENT_TEST_STRATEGY, - 'TestStrategyLegacyV1', + 'StrategyTestV2', ] args = get_args(args) start_backtesting(args) @@ -1221,14 +1221,13 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir): 'up to 2017-11-14 22:58:00 (0 days).', 'Parameter --enable-position-stacking detected ...', f'Running backtesting for Strategy {CURRENT_TEST_STRATEGY}', - 'Running backtesting for Strategy TestStrategyLegacyV1', + 'Running backtesting for Strategy StrategyTestV2', ] for line in exists: assert log_has(line, caplog) -@pytest.mark.filterwarnings("ignore:deprecated") def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdatadir, capsys): default_conf.update({ "use_exit_signal": True, @@ -1310,7 +1309,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat '--breakdown', 'day', '--strategy-list', CURRENT_TEST_STRATEGY, - 'TestStrategyLegacyV1', + 'StrategyTestV2', ] args = get_args(args) start_backtesting(args) @@ -1327,7 +1326,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat 'up to 2017-11-14 22:58:00 (0 days).', 'Parameter --enable-position-stacking detected ...', f'Running backtesting for Strategy {CURRENT_TEST_STRATEGY}', - 'Running backtesting for Strategy TestStrategyLegacyV1', + 'Running backtesting for Strategy StrategyTestV2', ] for line in exists: @@ -1592,7 +1591,7 @@ def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testda min_backtest_date = now - timedelta(weeks=4) load_backtest_metadata = MagicMock(return_value={ 'StrategyTestV2': {'run_id': '1', 'backtest_start_time': now.timestamp()}, - 'TestStrategyLegacyV1': {'run_id': run_id, 'backtest_start_time': start_time.timestamp()} + 'StrategyTestV3': {'run_id': run_id, 'backtest_start_time': start_time.timestamp()} }) load_backtest_stats = MagicMock(side_effect=[ { @@ -1601,9 +1600,9 @@ def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testda 'strategy_comparison': [{'key': 'StrategyTestV2'}] }, { - 'metadata': {'TestStrategyLegacyV1': {'run_id': '2'}}, - 'strategy': {'TestStrategyLegacyV1': {}}, - 'strategy_comparison': [{'key': 'TestStrategyLegacyV1'}] + 'metadata': {'StrategyTestV3': {'run_id': '2'}}, + 'strategy': {'StrategyTestV3': {}}, + 'strategy_comparison': [{'key': 'StrategyTestV3'}] } ]) mocker.patch('pathlib.Path.glob', return_value=[ @@ -1627,7 +1626,7 @@ def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testda '--cache', cache, '--strategy-list', 'StrategyTestV2', - 'TestStrategyLegacyV1', + 'StrategyTestV3', ] args = get_args(args) start_backtesting(args) @@ -1649,7 +1648,7 @@ def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testda assert backtestmock.call_count == 2 exists = [ 'Running backtesting for Strategy StrategyTestV2', - 'Running backtesting for Strategy TestStrategyLegacyV1', + 'Running backtesting for Strategy StrategyTestV3', 'Ignoring max_open_trades (--disable-max-market-positions was used) ...', 'Backtesting with data from 2017-11-14 21:17:00 up to 2017-11-14 22:58:00 (0 days).', ] @@ -1657,12 +1656,12 @@ def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testda assert backtestmock.call_count == 0 exists = [ 'Reusing result of previous backtest for StrategyTestV2', - 'Reusing result of previous backtest for TestStrategyLegacyV1', + 'Reusing result of previous backtest for StrategyTestV3', ] else: exists = [ 'Reusing result of previous backtest for StrategyTestV2', - 'Running backtesting for Strategy TestStrategyLegacyV1', + 'Running backtesting for Strategy StrategyTestV3', 'Ignoring max_open_trades (--disable-max-market-positions was used) ...', 'Backtesting with data from 2017-11-14 21:17:00 up to 2017-11-14 22:58:00 (0 days).', ] diff --git a/tests/strategy/strats/legacy_strategy_v1.py b/tests/strategy/strats/legacy_strategy_v1.py index bad2aa40d..a1fe4ee15 100644 --- a/tests/strategy/strats/legacy_strategy_v1.py +++ b/tests/strategy/strats/legacy_strategy_v1.py @@ -1,85 +1,29 @@ - -# --- Do not remove these libs --- -# Add your lib to import here -import talib.abstract as ta from pandas import DataFrame from freqtrade.strategy import IStrategy -# -------------------------------- - -# This class is a sample. Feel free to customize it. +# Dummy strategy - no longer loads but raises an exception. class TestStrategyLegacyV1(IStrategy): - """ - This is a test strategy using the legacy function headers, which will be - removed in a future update. - Please do not use this as a template, but refer to user_data/strategy/sample_strategy.py - for a uptodate version of this template. - """ - # Minimal ROI designed for the strategy. - # This attribute will be overridden if the config file contains "minimal_roi" minimal_roi = { "40": 0.0, "30": 0.01, "20": 0.02, "0": 0.04 } - - # Optimal stoploss designed for the strategy - # This attribute will be overridden if the config file contains "stoploss" stoploss = -0.10 timeframe = '5m' def populate_indicators(self, dataframe: DataFrame) -> DataFrame: - """ - Adds several different TA indicators to the given DataFrame - - Performance Note: For the best performance be frugal on the number of indicators - you are using. Let uncomment only the indicator you are using in your strategies - or your hyperopt configuration, otherwise you will waste your memory and CPU usage. - """ - - # Momentum Indicator - # ------------------------------------ - - # ADX - dataframe['adx'] = ta.ADX(dataframe) - - # TEMA - Triple Exponential Moving Average - dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9) return dataframe def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: - """ - Based on TA indicators, populates the buy signal for the given dataframe - :param dataframe: DataFrame - :return: DataFrame with buy column - """ - dataframe.loc[ - ( - (dataframe['adx'] > 30) & - (dataframe['tema'] > dataframe['tema'].shift(1)) & - (dataframe['volume'] > 0) - ), - 'buy'] = 1 return dataframe def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame: - """ - Based on TA indicators, populates the sell signal for the given dataframe - :param dataframe: DataFrame - :return: DataFrame with buy column - """ - dataframe.loc[ - ( - (dataframe['adx'] > 70) & - (dataframe['tema'] < dataframe['tema'].shift(1)) & - (dataframe['volume'] > 0) - ), - 'sell'] = 1 + return dataframe diff --git a/tests/strategy/test_interface.py b/tests/strategy/test_interface.py index a86d69135..ea81fe968 100644 --- a/tests/strategy/test_interface.py +++ b/tests/strategy/test_interface.py @@ -686,7 +686,7 @@ def test_is_pair_locked(default_conf): def test_is_informative_pairs_callback(default_conf): - default_conf.update({'strategy': 'TestStrategyLegacyV1'}) + default_conf.update({'strategy': 'StrategyTestV2'}) strategy = StrategyResolver.load_strategy(default_conf) # Should return empty # Uses fallback to base implementation diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py index e74a2a022..85f7961ed 100644 --- a/tests/strategy/test_strategy_loading.py +++ b/tests/strategy/test_strategy_loading.py @@ -100,7 +100,7 @@ def test_load_strategy_noname(default_conf): @pytest.mark.filterwarnings("ignore:deprecated") -@pytest.mark.parametrize('strategy_name', ['StrategyTestV2', 'TestStrategyLegacyV1']) +@pytest.mark.parametrize('strategy_name', ['StrategyTestV2']) def test_strategy_pre_v3(result, default_conf, strategy_name): default_conf.update({'strategy': strategy_name}) @@ -346,40 +346,6 @@ def test_strategy_override_use_exit_profit_only(caplog, default_conf): assert log_has("Override strategy 'exit_profit_only' with value in config file: True.", caplog) -@pytest.mark.filterwarnings("ignore:deprecated") -def test_deprecate_populate_indicators(result, default_conf): - default_location = Path(__file__).parent / "strats" - default_conf.update({'strategy': 'TestStrategyLegacyV1', - 'strategy_path': default_location}) - strategy = StrategyResolver.load_strategy(default_conf) - with warnings.catch_warnings(record=True) as w: - # Cause all warnings to always be triggered. - warnings.simplefilter("always") - indicators = strategy.advise_indicators(result, {'pair': 'ETH/BTC'}) - assert len(w) == 1 - assert issubclass(w[-1].category, DeprecationWarning) - assert "deprecated - check out the Sample strategy to see the current function headers!" \ - in str(w[-1].message) - - with warnings.catch_warnings(record=True) as w: - # Cause all warnings to always be triggered. - warnings.simplefilter("always") - strategy.advise_entry(indicators, {'pair': 'ETH/BTC'}) - assert len(w) == 1 - assert issubclass(w[-1].category, DeprecationWarning) - assert "deprecated - check out the Sample strategy to see the current function headers!" \ - in str(w[-1].message) - - with warnings.catch_warnings(record=True) as w: - # Cause all warnings to always be triggered. - warnings.simplefilter("always") - strategy.advise_exit(indicators, {'pair': 'ETH_BTC'}) - assert len(w) == 1 - assert issubclass(w[-1].category, DeprecationWarning) - assert "deprecated - check out the Sample strategy to see the current function headers!" \ - in str(w[-1].message) - - @pytest.mark.filterwarnings("ignore:deprecated") def test_missing_implements(default_conf, caplog): @@ -438,33 +404,14 @@ def test_missing_implements(default_conf, caplog): StrategyResolver.load_strategy(default_conf) -@pytest.mark.filterwarnings("ignore:deprecated") -def test_call_deprecated_function(result, default_conf, caplog): +def test_call_deprecated_function(default_conf): default_location = Path(__file__).parent / "strats" del default_conf['timeframe'] default_conf.update({'strategy': 'TestStrategyLegacyV1', 'strategy_path': default_location}) - strategy = StrategyResolver.load_strategy(default_conf) - metadata = {'pair': 'ETH/BTC'} - - # Make sure we are using a legacy function - assert strategy._populate_fun_len == 2 - assert strategy._buy_fun_len == 2 - assert strategy._sell_fun_len == 2 - assert strategy.INTERFACE_VERSION == 1 - assert strategy.timeframe == '5m' - - indicator_df = strategy.advise_indicators(result, metadata=metadata) - assert isinstance(indicator_df, DataFrame) - assert 'adx' in indicator_df.columns - - enterdf = strategy.advise_entry(result, metadata=metadata) - assert isinstance(enterdf, DataFrame) - assert 'enter_long' in enterdf.columns - - exitdf = strategy.advise_exit(result, metadata=metadata) - assert isinstance(exitdf, DataFrame) - assert 'exit_long' in exitdf + with pytest.raises(OperationalException, + match=r"Strategy Interface v1 is no longer supported.*"): + StrategyResolver.load_strategy(default_conf) def test_strategy_interface_versioning(result, default_conf): @@ -472,10 +419,6 @@ def test_strategy_interface_versioning(result, default_conf): strategy = StrategyResolver.load_strategy(default_conf) metadata = {'pair': 'ETH/BTC'} - # Make sure we are using a legacy function - assert strategy._populate_fun_len == 3 - assert strategy._buy_fun_len == 3 - assert strategy._sell_fun_len == 3 assert strategy.INTERFACE_VERSION == 2 indicator_df = strategy.advise_indicators(result, metadata=metadata) From 9bb0f1f675d211a3dd95359b6129c10628dcc958 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 07:09:08 +0200 Subject: [PATCH 112/159] Move legacy strategy to "broken strats" folder --- tests/commands/test_commands.py | 16 ++++++++-------- tests/rpc/test_rpc_apiserver.py | 1 - .../{ => broken_strats}/legacy_strategy_v1.py | 1 + tests/strategy/test_strategy_loading.py | 9 ++++----- 4 files changed, 13 insertions(+), 14 deletions(-) rename tests/strategy/strats/{ => broken_strats}/legacy_strategy_v1.py (97%) diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index d1f54ad52..37eeda86a 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -859,8 +859,8 @@ def test_start_list_strategies(capsys): # pargs['config'] = None start_list_strategies(pargs) captured = capsys.readouterr() - assert "TestStrategyLegacyV1" in captured.out - assert "legacy_strategy_v1.py" not in captured.out + assert "StrategyTestV2" in captured.out + assert "strategy_test_v2.py" not in captured.out assert CURRENT_TEST_STRATEGY in captured.out # Test regular output @@ -874,8 +874,8 @@ def test_start_list_strategies(capsys): # pargs['config'] = None start_list_strategies(pargs) captured = capsys.readouterr() - assert "TestStrategyLegacyV1" in captured.out - assert "legacy_strategy_v1.py" in captured.out + assert "StrategyTestV2" in captured.out + assert "strategy_test_v2.py" in captured.out assert CURRENT_TEST_STRATEGY in captured.out # Test color output @@ -888,8 +888,8 @@ def test_start_list_strategies(capsys): # pargs['config'] = None start_list_strategies(pargs) captured = capsys.readouterr() - assert "TestStrategyLegacyV1" in captured.out - assert "legacy_strategy_v1.py" in captured.out + assert "StrategyTestV2" in captured.out + assert "strategy_test_v2.py" in captured.out assert CURRENT_TEST_STRATEGY in captured.out assert "LOAD FAILED" in captured.out # Recursive @@ -907,8 +907,8 @@ def test_start_list_strategies(capsys): # pargs['config'] = None start_list_strategies(pargs) captured = capsys.readouterr() - assert "TestStrategyLegacyV1" in captured.out - assert "legacy_strategy_v1.py" in captured.out + assert "StrategyTestV2" in captured.out + assert "strategy_test_v2.py" in captured.out assert "StrategyTestV2" in captured.out assert "TestStrategyNoImplements" in captured.out assert str(Path("broken_strats/broken_futures_strategies.py")) in captured.out diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index af8361571..4910213b4 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1389,7 +1389,6 @@ def test_api_strategies(botclient): 'StrategyTestV2', 'StrategyTestV3', 'StrategyTestV3Futures', - 'TestStrategyLegacyV1', ]} diff --git a/tests/strategy/strats/legacy_strategy_v1.py b/tests/strategy/strats/broken_strats/legacy_strategy_v1.py similarity index 97% rename from tests/strategy/strats/legacy_strategy_v1.py rename to tests/strategy/strats/broken_strats/legacy_strategy_v1.py index a1fe4ee15..f3b8c2696 100644 --- a/tests/strategy/strats/legacy_strategy_v1.py +++ b/tests/strategy/strats/broken_strats/legacy_strategy_v1.py @@ -1,3 +1,4 @@ +# type: ignore from pandas import DataFrame from freqtrade.strategy import IStrategy diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py index 85f7961ed..3ed1eb0ce 100644 --- a/tests/strategy/test_strategy_loading.py +++ b/tests/strategy/test_strategy_loading.py @@ -1,6 +1,5 @@ # pragma pylint: disable=missing-docstring, protected-access, C0103 import logging -import warnings from base64 import urlsafe_b64encode from pathlib import Path @@ -35,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) == 5 assert isinstance(strategies[0], dict) @@ -43,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) == 6 # 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]) == 5 assert len([x for x in strategies if x['class'] is None]) == 1 @@ -405,7 +404,7 @@ def test_missing_implements(default_conf, caplog): def test_call_deprecated_function(default_conf): - default_location = Path(__file__).parent / "strats" + default_location = Path(__file__).parent / "strats/broken_strats/" del default_conf['timeframe'] default_conf.update({'strategy': 'TestStrategyLegacyV1', 'strategy_path': default_location}) From ad6e5c53120053556b4cd0e19581a853e3e02432 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 07:41:51 +0200 Subject: [PATCH 113/159] Test informative fallback again --- tests/strategy/strats/strategy_test_v2.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tests/strategy/strats/strategy_test_v2.py b/tests/strategy/strats/strategy_test_v2.py index 8996b227a..85ff856e1 100644 --- a/tests/strategy/strats/strategy_test_v2.py +++ b/tests/strategy/strats/strategy_test_v2.py @@ -56,19 +56,6 @@ class StrategyTestV2(IStrategy): # By default this strategy does not use Position Adjustments position_adjustment_enable = False - def informative_pairs(self): - """ - Define additional, informative pair/interval combinations to be cached from the exchange. - These pair/interval combinations are non-tradeable, unless they are part - of the whitelist as well. - For more information, please consult the documentation - :return: List of tuples in the format (pair, interval) - Sample: return [("ETH/USDT", "5m"), - ("BTC/USDT", "15m"), - ] - """ - return [] - def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ Adds several different TA indicators to the given DataFrame From 86b3aac9ba8a0db45c986fa8ebda7bb19292fe33 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 08:38:02 +0200 Subject: [PATCH 114/159] Fix FTX not fetching the very latest data --- freqtrade/exchange/exchange.py | 9 ++++++--- freqtrade/exchange/ftx.py | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index ab063762b..2eb705b53 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -64,6 +64,7 @@ class Exchange: "ohlcv_params": {}, "ohlcv_candle_limit": 500, "ohlcv_partial_candle": True, + "ohlcv_require_since": False, # Check https://github.com/ccxt/ccxt/issues/10767 for removal of ohlcv_volume_currency "ohlcv_volume_currency": "base", # "base" or "quote" "tickers_have_quoteVolume": True, @@ -1710,7 +1711,8 @@ class Exchange: def _build_coroutine(self, pair: str, timeframe: str, candle_type: CandleType, since_ms: Optional[int]) -> Coroutine: - if not since_ms and self.required_candle_call_count > 1: + if (not since_ms + and (self._ft_has["ohlcv_require_since"] or self.required_candle_call_count > 1)): # Multiple calls for one pair - to get more history one_call = timeframe_to_msecs(timeframe) * self.ohlcv_candle_limit(timeframe) move_to = one_call * self.required_candle_call_count @@ -1829,17 +1831,18 @@ class Exchange: pair, timeframe, since_ms, s ) params = deepcopy(self._ft_has.get('ohlcv_params', {})) + candle_limit = self.ohlcv_candle_limit(timeframe) if candle_type != CandleType.SPOT: params.update({'price': candle_type}) if candle_type != CandleType.FUNDING_RATE: data = await self._api_async.fetch_ohlcv( pair, timeframe=timeframe, since=since_ms, - limit=self.ohlcv_candle_limit(timeframe), params=params) + limit=candle_limit, params=params) else: # Funding rate data = await self._api_async.fetch_funding_rate_history( pair, since=since_ms, - limit=self.ohlcv_candle_limit(timeframe)) + limit=candle_limit) # Convert funding rate to candle pattern data = [[x['timestamp'], x['fundingRate'], 0, 0, 0, 0] for x in data] # Some exchanges sort OHLCV in ASC order and others in DESC. diff --git a/freqtrade/exchange/ftx.py b/freqtrade/exchange/ftx.py index f20aab138..d2dcf84a6 100644 --- a/freqtrade/exchange/ftx.py +++ b/freqtrade/exchange/ftx.py @@ -20,6 +20,7 @@ class Ftx(Exchange): _ft_has: Dict = { "stoploss_on_exchange": True, "ohlcv_candle_limit": 1500, + "ohlcv_require_since": True, "ohlcv_volume_currency": "quote", "mark_ohlcv_price": "index", "mark_ohlcv_timeframe": "1h", From 7b02114ad2826bf4260ec98d47d9cd9e9a191d78 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 09:49:51 +0200 Subject: [PATCH 115/159] Restrict trading pairs with too low precision closes #6606 --- freqtrade/exchange/exchange.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 2eb705b53..d4741bd64 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -369,6 +369,9 @@ class Exchange: return ( 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', None) > 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))) From 6d576bc02d4474b29de678052b3a420d2aa2cc4d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 10:15:07 +0200 Subject: [PATCH 116/159] Check pre-commit verison updates --- .github/workflows/ci.yml | 21 ++++++++++++--- .pre-commit-config.yaml | 7 +++++ build_helpers/pre_commit_update.py | 42 ++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 build_helpers/pre_commit_update.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1902a6c45..35c237837 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -265,6 +265,21 @@ jobs: details: Test Failed webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} + mypy_version_check: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: 3.9 + + - name: pre-commit dependencies + run: | + pip install pyaml + python build_helpers/pre_commit_update.py + docs_check: runs-on: ubuntu-20.04 steps: @@ -277,7 +292,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: 3.9 - name: Documentation build run: | @@ -304,7 +319,7 @@ jobs: # Notify only once - when CI completes (and after deploy) in case it's successfull notify-complete: - needs: [ build_linux, build_macos, build_windows, docs_check ] + needs: [ build_linux, build_macos, build_windows, docs_check, mypy_version_check ] runs-on: ubuntu-20.04 steps: @@ -325,7 +340,7 @@ jobs: webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} deploy: - needs: [ build_linux, build_macos, build_windows, docs_check ] + needs: [ build_linux, build_macos, build_windows, docs_check, mypy_version_check ] runs-on: ubuntu-20.04 if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'release') && github.repository == 'freqtrade/freqtrade' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 316baf0e3..f223f0b9b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,13 @@ repos: rev: "v0.942" hooks: - id: mypy + args: [ freqtrade ] + additional_dependencies: + - types-cachetools==5.0.1 + - types-filelock==3.2.5 + - types-requests==2.27.19 + - types-tabulate==0.8.7 + - types-python-dateutil==2.8.11 # stages: [push] - repo: https://github.com/pycqa/isort diff --git a/build_helpers/pre_commit_update.py b/build_helpers/pre_commit_update.py new file mode 100644 index 000000000..8724d8ade --- /dev/null +++ b/build_helpers/pre_commit_update.py @@ -0,0 +1,42 @@ +# File used in CI to ensure pre-commit dependencies are kept uptodate. + +import sys +from pathlib import Path + +import yaml + + +pre_commit_file = Path('.pre-commit-config.yaml') +require_dev = Path('requirements-dev.txt') + +with require_dev.open('r') as rfile: + requirements = rfile.readlines() + +# Extract types only +type_reqs = [r.strip('\n') for r in requirements if r.startswith('types-')] + +with pre_commit_file.open('r') as file: + f = yaml.load(file, Loader=yaml.FullLoader) + + +mypy_repo = [repo for repo in f['repos'] if repo['repo'] + == 'https://github.com/pre-commit/mirrors-mypy'] + +hooks = mypy_repo[0]['hooks'][0]['additional_dependencies'] + +errors = [] +for hook in hooks: + if hook not in type_reqs: + errors.append(f"{hook} is missing in requirements-dev.txt.") + +for req in type_reqs: + if req not in hooks: + errors.append(f"{req} is missing in pre-config file.") + + +if errors: + for e in errors: + print(e) + sys.exit(1) + +sys.exit(0) From fc118d0e95d38e7f5a655c79fc3de41ab9f2f537 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 10:19:31 +0200 Subject: [PATCH 117/159] Re-align dependencies --- .pre-commit-config.yaml | 4 ++-- requirements-dev.txt | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f223f0b9b..0dd343bb8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,9 +15,9 @@ repos: additional_dependencies: - types-cachetools==5.0.1 - types-filelock==3.2.5 - - types-requests==2.27.19 + - types-requests==2.27.20 - types-tabulate==0.8.7 - - types-python-dateutil==2.8.11 + - types-python-dateutil==2.8.12 # stages: [push] - repo: https://github.com/pycqa/isort diff --git a/requirements-dev.txt b/requirements-dev.txt index b0210d64a..c4fe366a5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -26,6 +26,4 @@ types-cachetools==5.0.1 types-filelock==3.2.5 types-requests==2.27.20 types-tabulate==0.8.7 - -# Extensions to datetime library types-python-dateutil==2.8.12 From 4143ebbeae53eb27706cf15573f4f36b905ac8e0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 10:51:11 +0200 Subject: [PATCH 118/159] Add CAGR calculation to backtesting --- docs/backtesting.md | 2 ++ freqtrade/data/btanalysis.py | 11 +++++++++++ freqtrade/optimize/optimize_reports.py | 4 +++- tests/data/test_btanalysis.py | 27 +++++++++++++++++++------- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/docs/backtesting.md b/docs/backtesting.md index f732068f1..a0a304400 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -299,6 +299,7 @@ A backtesting result will look like that: | Final balance | 0.01762792 BTC | | Absolute profit | 0.00762792 BTC | | Total profit % | 76.2% | +| CAGR % | 460.87% | | Trades per day | 3.575 | | Avg. stake amount | 0.001 BTC | | Total trade volume | 0.429 BTC | @@ -388,6 +389,7 @@ It contains some useful key metrics about performance of your strategy on backte | Final balance | 0.01762792 BTC | | Absolute profit | 0.00762792 BTC | | Total profit % | 76.2% | +| CAGR % | 460.87% | | Avg. stake amount | 0.001 BTC | | Total trade volume | 0.429 BTC | | | | diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index 8abcc6747..206a6f5f3 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -553,3 +553,14 @@ def calculate_csum(trades: pd.DataFrame, starting_balance: float = 0) -> Tuple[f csum_max = csum_df['sum'].max() + starting_balance return csum_min, csum_max + + +def calculate_cagr(days_passed: int, starting_balance: float, final_balance: float) -> float: + """ + Calculate CAGR + :param days_passed: Days passed between start and ending balance + :param starting_balance: Starting balance + :param final_balance: Final balance to calculate CAGR against + :return: CAGR + """ + return (final_balance / starting_balance) ** (1 / (days_passed / 365)) - 1 diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 0ceb3a411..e8bd035d1 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -9,7 +9,7 @@ from pandas import DataFrame, to_datetime from tabulate import tabulate from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT -from freqtrade.data.btanalysis import (calculate_csum, calculate_market_change, +from freqtrade.data.btanalysis import (calculate_cagr, calculate_csum, calculate_market_change, calculate_max_drawdown) from freqtrade.misc import (decimals_per_coin, file_dump_joblib, file_dump_json, get_backtest_metadata_filename, round_coin_value) @@ -446,6 +446,7 @@ def generate_strategy_stats(pairlist: List[str], 'profit_total_abs': results['profit_abs'].sum(), 'profit_total_long_abs': results.loc[~results['is_short'], 'profit_abs'].sum(), 'profit_total_short_abs': results.loc[results['is_short'], 'profit_abs'].sum(), + 'cagr': calculate_cagr(backtest_days, start_balance, content['final_balance']), 'backtest_start': min_date.strftime(DATETIME_PRINT_FORMAT), 'backtest_start_ts': int(min_date.timestamp() * 1000), 'backtest_end': max_date.strftime(DATETIME_PRINT_FORMAT), @@ -746,6 +747,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: ('Absolute profit ', round_coin_value(strat_results['profit_total_abs'], strat_results['stake_currency'])), ('Total profit %', f"{strat_results['profit_total']:.2%}"), + ('CAGR %', f"{strat_results['cagr']:.2%}"), ('Trades per day', strat_results['trades_per_day']), ('Avg. daily profit %', f"{(strat_results['profit_total'] / strat_results['backtest_days']):.2%}"), diff --git a/tests/data/test_btanalysis.py b/tests/data/test_btanalysis.py index 2b53e4900..eaf703b2d 100644 --- a/tests/data/test_btanalysis.py +++ b/tests/data/test_btanalysis.py @@ -8,13 +8,13 @@ from pandas import DataFrame, DateOffset, Timestamp, to_datetime from freqtrade.configuration import TimeRange from freqtrade.constants import LAST_BT_RESULT_FN -from freqtrade.data.btanalysis import (BT_DATA_COLUMNS, analyze_trade_parallelism, calculate_csum, - calculate_market_change, calculate_max_drawdown, - calculate_underwater, combine_dataframes_with_mean, - create_cum_profit, extract_trades_of_period, - get_latest_backtest_filename, get_latest_hyperopt_file, - load_backtest_data, load_backtest_metadata, load_trades, - load_trades_from_db) +from freqtrade.data.btanalysis import (BT_DATA_COLUMNS, analyze_trade_parallelism, calculate_cagr, + calculate_csum, calculate_market_change, + calculate_max_drawdown, calculate_underwater, + combine_dataframes_with_mean, create_cum_profit, + extract_trades_of_period, get_latest_backtest_filename, + get_latest_hyperopt_file, load_backtest_data, + load_backtest_metadata, load_trades, load_trades_from_db) from freqtrade.data.history import load_data, load_pair_history from freqtrade.exceptions import OperationalException from tests.conftest import CURRENT_TEST_STRATEGY, create_mock_trades @@ -336,6 +336,19 @@ def test_calculate_csum(testdatadir): csum_min, csum_max = calculate_csum(DataFrame()) +@pytest.mark.parametrize('start,end,days, expected', [ + (64900, 176000, 3 * 365, 0.3945), + (64900, 176000, 365, 1.7119), + (1000, 1000, 365, 0.0), + (1000, 1500, 365, 0.5), + (1000, 1500, 100, 3.3927), # sub year + (0.01000000, 0.01762792, 120, 4.6087), # sub year BTC values +]) +def test_calculate_cagr(start, end, days, expected): + + assert round(calculate_cagr(days, start, end), 4) == expected + + def test_calculate_max_drawdown2(): values = [0.011580, 0.010048, 0.011340, 0.012161, 0.010416, 0.010009, 0.020024, -0.024662, -0.022350, 0.020496, -0.029859, -0.030511, 0.010041, 0.010872, From 500fdc2759639d9275ab82bfbcaaa01e48017eae Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 11:12:35 +0200 Subject: [PATCH 119/159] run mypy also against tests --- .github/workflows/ci.yml | 4 ++-- .pre-commit-config.yaml | 2 +- freqtrade/strategy/informative_decorator.py | 2 +- freqtrade/strategy/interface.py | 2 +- setup.cfg | 4 ++++ 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35c237837..5bafe9cb8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,7 +100,7 @@ jobs: - name: Mypy run: | - mypy freqtrade scripts + mypy freqtrade scripts tests - name: Discord notification uses: rjstone/discord-webhook-notify@v1 @@ -255,7 +255,7 @@ jobs: - name: Mypy run: | - mypy freqtrade scripts + mypy freqtrade scripts tests - name: Discord notification uses: rjstone/discord-webhook-notify@v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0dd343bb8..d980fc4e9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: rev: "v0.942" hooks: - id: mypy - args: [ freqtrade ] + args: [ freqtrade, scripts, tests ] additional_dependencies: - types-cachetools==5.0.1 - types-filelock==3.2.5 diff --git a/freqtrade/strategy/informative_decorator.py b/freqtrade/strategy/informative_decorator.py index 0dd5320cd..7dfdf5a8c 100644 --- a/freqtrade/strategy/informative_decorator.py +++ b/freqtrade/strategy/informative_decorator.py @@ -23,7 +23,7 @@ class InformativeData: def informative(timeframe: str, asset: str = '', fmt: Optional[Union[str, Callable[[Any], str]]] = None, *, - candle_type: Optional[CandleType] = None, + candle_type: Optional[Union[CandleType, str]] = None, ffill: bool = True) -> Callable[[PopulateIndicators], PopulateIndicators]: """ A decorator for populate_indicators_Nn(self, dataframe, metadata), allowing these functions to diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 0ec3895bc..300010b83 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -110,7 +110,7 @@ class IStrategy(ABC, HyperStrategyMixin): # Class level variables (intentional) containing # the dataprovider (dp) (access to other candles, historic data, ...) # and wallets - access to the current balance. - dp: Optional[DataProvider] + dp: DataProvider wallets: Optional[Wallets] = None # Filled from configuration stake_currency: str diff --git a/setup.cfg b/setup.cfg index a33ceda1f..edbd320c3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -53,6 +53,10 @@ exclude = [mypy] ignore_missing_imports = True warn_unused_ignores = True +exclude = (?x)( + ^build_helpers\.py$ + ) + [mypy-tests.*] ignore_errors = True From 2b3f68396081a41861797ef0a4abc3c08221765f Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 11:23:45 +0200 Subject: [PATCH 120/159] Update pre-commit to exclude build-helpers --- .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 d980fc4e9..2170b704a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: rev: "v0.942" hooks: - id: mypy - args: [ freqtrade, scripts, tests ] + exclude: build_helpers additional_dependencies: - types-cachetools==5.0.1 - types-filelock==3.2.5 From 580da21ddaa3e9fa8a0016434bc0ffbaf9794276 Mon Sep 17 00:00:00 2001 From: froggleston Date: Mon, 25 Apr 2022 10:31:19 +0100 Subject: [PATCH 121/159] Move df append to pd concat --- freqtrade/optimize/backtesting.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 freqtrade/optimize/backtesting.py diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py old mode 100644 new mode 100755 index 5442e425b..217e6ff54 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -10,6 +10,7 @@ from datetime import datetime, timedelta, timezone from typing import Any, Dict, List, Optional, Tuple from numpy import nan +import pandas as pd from pandas import DataFrame from freqtrade import constants @@ -1093,7 +1094,7 @@ class Backtesting: for t, v in pairresults.open_date.items(): allinds = pairdf.loc[(pairdf['date'] < v)] signal_inds = allinds.iloc[[-1]] - signal_candles_only_df = signal_candles_only_df.append(signal_inds) + signal_candles_only_df = pd.concat([signal_candles_only_df, signal_inds]) signal_candles_only[pair] = signal_candles_only_df From 431c539cbdf3e207d9a7afdc299a14f3b245f547 Mon Sep 17 00:00:00 2001 From: froggleston Date: Mon, 25 Apr 2022 10:42:24 +0100 Subject: [PATCH 122/159] Fix isort import order --- freqtrade/optimize/backtesting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 217e6ff54..27e14ba93 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -9,8 +9,8 @@ from copy import deepcopy from datetime import datetime, timedelta, timezone from typing import Any, Dict, List, Optional, Tuple -from numpy import nan import pandas as pd +from numpy import nan from pandas import DataFrame from freqtrade import constants From 44000ae0b390ce4a4fa48e4fc588863fdafe8c87 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 17:37:25 +0200 Subject: [PATCH 123/159] Fix CAGR missing for old results --- freqtrade/optimize/optimize_reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index e8bd035d1..dd058aff4 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -747,7 +747,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: ('Absolute profit ', round_coin_value(strat_results['profit_total_abs'], strat_results['stake_currency'])), ('Total profit %', f"{strat_results['profit_total']:.2%}"), - ('CAGR %', f"{strat_results['cagr']:.2%}"), + ('CAGR %', f"{strat_results['cagr']:.2%}" if 'cagr' in strat_results else 'N/A'), ('Trades per day', strat_results['trades_per_day']), ('Avg. daily profit %', f"{(strat_results['profit_total'] / strat_results['backtest_days']):.2%}"), From 0b90e1d30921b8cec6e97e612e44e51ea225b0c8 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Fri, 1 Apr 2022 08:39:56 -0600 Subject: [PATCH 124/159] Added bot_start callback to strategy interface --- freqtrade/freqtradebot.py | 2 ++ freqtrade/strategy/interface.py | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 57d7cac3c..bee6c4746 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -122,6 +122,8 @@ class FreqtradeBot(LoggingMixin): self._schedule.every().day.at(t).do(update) self.last_process = datetime(1970, 1, 1, tzinfo=timezone.utc) + self.strategy.bot_start() + def notify_status(self, msg: str) -> None: """ Public method for users of this class (worker, etc.) to send notifications diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 300010b83..40744ed08 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -193,6 +193,13 @@ class IStrategy(ABC, HyperStrategyMixin): """ return self.populate_sell_trend(dataframe, metadata) + def bot_start(self, **kwargs) -> None: + """ + Called only once after bot instantiation. + :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. + """ + pass + def bot_loop_start(self, **kwargs) -> None: """ Called at the start of the bot iteration (one loop). From bf7da35e31a3d9a98fff35cd098ecaf83f6d91f2 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Fri, 1 Apr 2022 09:25:03 -0600 Subject: [PATCH 125/159] strategy callback on_whitelist_update --- freqtrade/freqtradebot.py | 4 ++++ freqtrade/strategy/interface.py | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index bee6c4746..949d821b3 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -179,6 +179,7 @@ class FreqtradeBot(LoggingMixin): # Query trades from persistence layer trades = Trade.get_open_trades() + current_pair_whitelist = self.active_pair_whitelist self.active_pair_whitelist = self._refresh_active_whitelist(trades) # Refreshing candles @@ -214,6 +215,9 @@ class FreqtradeBot(LoggingMixin): Trade.commit() self.last_process = datetime.now(timezone.utc) + if current_pair_whitelist != self.active_pair_whitelist: + self.strategy.on_whitelist_update() + def process_stopped(self) -> None: """ Close all orders that were left open diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 40744ed08..00d18fa7b 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -209,6 +209,13 @@ class IStrategy(ABC, HyperStrategyMixin): """ pass + def on_whitelist_update(self, **kwargs) -> None: + """ + Called every time the whitelist updates + :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. + """ + pass + def check_buy_timeout(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> bool: """ From d92761b2b168a19eea764864c5fb9612a379c510 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sun, 3 Apr 2022 02:53:44 -0600 Subject: [PATCH 126/159] Revert "strategy callback on_whitelist_update" This reverts commit 39798dc1192161c3060830dd4684571aa86b7821. --- freqtrade/freqtradebot.py | 4 ---- freqtrade/strategy/interface.py | 7 ------- 2 files changed, 11 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 949d821b3..bee6c4746 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -179,7 +179,6 @@ class FreqtradeBot(LoggingMixin): # Query trades from persistence layer trades = Trade.get_open_trades() - current_pair_whitelist = self.active_pair_whitelist self.active_pair_whitelist = self._refresh_active_whitelist(trades) # Refreshing candles @@ -215,9 +214,6 @@ class FreqtradeBot(LoggingMixin): Trade.commit() self.last_process = datetime.now(timezone.utc) - if current_pair_whitelist != self.active_pair_whitelist: - self.strategy.on_whitelist_update() - def process_stopped(self) -> None: """ Close all orders that were left open diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 00d18fa7b..40744ed08 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -209,13 +209,6 @@ class IStrategy(ABC, HyperStrategyMixin): """ pass - def on_whitelist_update(self, **kwargs) -> None: - """ - Called every time the whitelist updates - :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - """ - pass - def check_buy_timeout(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> bool: """ From 4fd904e0a91ecf03020060c3d718382775bd143b Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sun, 3 Apr 2022 10:28:09 -0600 Subject: [PATCH 127/159] added bot_start to backtesting --- freqtrade/optimize/backtesting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 27e14ba93..1789290bc 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -182,6 +182,7 @@ class Backtesting: # since a "perfect" stoploss-exit is assumed anyway # And the regular "stoploss" function would not apply to that case self.strategy.order_types['stoploss_on_exchange'] = False + self.strategy.bot_start() def _load_protections(self, strategy: IStrategy): if self.config.get('enable_protections', False): From e09b4498fa419f0088b38cec2cef6c78307ee2e6 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 25 Apr 2022 17:30:49 -0600 Subject: [PATCH 128/159] added bot_start call to plot/plotting --- freqtrade/plot/plotting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py index 747248be7..5337016f3 100644 --- a/freqtrade/plot/plotting.py +++ b/freqtrade/plot/plotting.py @@ -610,6 +610,7 @@ def load_and_plot_trades(config: Dict[str, Any]): exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config) IStrategy.dp = DataProvider(config, exchange) + strategy.bot_start() plot_elements = init_plotscript(config, list(exchange.markets), strategy.startup_candle_count) timerange = plot_elements['timerange'] trades = plot_elements['trades'] From e76c6e8ad31a525802ec35fa0dd8c6e264d32328 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 25 Apr 2022 17:32:48 -0600 Subject: [PATCH 129/159] added bot_start call to edge_positioning.__init__ --- freqtrade/edge/edge_positioning.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/freqtrade/edge/edge_positioning.py b/freqtrade/edge/edge_positioning.py index 2fe41a17b..5dc84f172 100644 --- a/freqtrade/edge/edge_positioning.py +++ b/freqtrade/edge/edge_positioning.py @@ -90,6 +90,8 @@ class Edge: self.config['exchange']['pair_whitelist'], list(self.exchange.markets))[0]) except IndexError: self.fee = None + + strategy.bot_start() def calculate(self, pairs: List[str]) -> bool: if self.fee is None and pairs: From 810e190e164be61a530e4d550c246dddbcdb4f1c Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 25 Apr 2022 17:46:40 -0600 Subject: [PATCH 130/159] added tests for bot_start --- tests/optimize/test_backtesting.py | 1 + tests/optimize/test_edge_cli.py | 1 + tests/strategy/strats/strategy_test_v3.py | 5 +++++ tests/strategy/test_default_strategy.py | 1 + tests/test_plotting.py | 1 + 5 files changed, 9 insertions(+) diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index d7ee4a042..16d1aa2a5 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -312,6 +312,7 @@ def test_backtesting_init(mocker, default_conf, order_types) -> None: get_fee.assert_called() assert backtesting.fee == 0.5 assert not backtesting.strategy.order_types["stoploss_on_exchange"] + assert backtesting.strategy.bot_started is True def test_backtesting_init_no_timeframe(mocker, default_conf, caplog) -> None: diff --git a/tests/optimize/test_edge_cli.py b/tests/optimize/test_edge_cli.py index f0f436a43..d9711b318 100644 --- a/tests/optimize/test_edge_cli.py +++ b/tests/optimize/test_edge_cli.py @@ -94,6 +94,7 @@ def test_edge_init(mocker, edge_conf) -> None: assert edge_cli.config == edge_conf assert edge_cli.config['stake_amount'] == 'unlimited' assert callable(edge_cli.edge.calculate) + assert edge_conf['strategy'].bot_started is True def test_edge_init_fee(mocker, edge_conf) -> None: diff --git a/tests/strategy/strats/strategy_test_v3.py b/tests/strategy/strats/strategy_test_v3.py index 372e29412..df83d3663 100644 --- a/tests/strategy/strats/strategy_test_v3.py +++ b/tests/strategy/strats/strategy_test_v3.py @@ -82,6 +82,11 @@ class StrategyTestV3(IStrategy): # }) # return prot + bot_started = False + + def bot_start(self): + self.bot_started = True + def informative_pairs(self): return [] diff --git a/tests/strategy/test_default_strategy.py b/tests/strategy/test_default_strategy.py index 5cb8fce16..a60274afd 100644 --- a/tests/strategy/test_default_strategy.py +++ b/tests/strategy/test_default_strategy.py @@ -32,6 +32,7 @@ def test_strategy_test_v3(result, fee, is_short, side): assert type(indicators) is DataFrame assert type(strategy.populate_buy_trend(indicators, metadata)) is DataFrame assert type(strategy.populate_sell_trend(indicators, metadata)) is DataFrame + assert strategy.bot_started is True trade = Trade( open_rate=19_000, diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 97f367608..f0a28c4eb 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -58,6 +58,7 @@ def test_init_plotscript(default_conf, mocker, testdatadir): assert "ohlcv" in ret assert "TRX/BTC" in ret["ohlcv"] assert "ADA/BTC" in ret["ohlcv"] + assert default_conf['strategy'].bot_started is True def test_add_indicators(default_conf, testdatadir, caplog): From 7f035a9d5384993dc195a0a5d8f2e22c5fc74d75 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 25 Apr 2022 17:59:50 -0600 Subject: [PATCH 131/159] added docs for bot_start --- docs/strategy-callbacks.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 7ec600a58..a53a6992c 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -7,6 +7,7 @@ Depending on the callback used, they may be called when entering / exiting a tra Currently available callbacks: +* [`bot_start()`](#bot-start) * [`bot_loop_start()`](#bot-loop-start) * [`custom_stake_amount()`](#stake-size-management) * [`custom_exit()`](#custom-exit-signal) @@ -21,6 +22,31 @@ Currently available callbacks: !!! Tip "Callback calling sequence" You can find the callback calling sequence in [bot-basics](bot-basics.md#bot-execution-logic) +## Bot start + +A simple callback which is called once when the bot starts. +This can be used to perform actions that must only be performed once and runs after dataprovider and wallet are set + +``` python +import asyncio + +class AwesomeStrategy(IStrategy): + + # ... populate_* methods + + async def some_asynchronous_task(self): + self.dp['remote_data'] = requests.get('https://some_remote_source.example.com') + + def bot_start(self, **kwargs) -> None: + """ + Called only once after bot instantiation. + :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. + """ + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + self.loop.run_until_complete(self.some_asynchronous_task()) + +``` ## Bot loop start A simple callback which is called once at the start of every bot throttling iteration (roughly every 5 seconds, unless configured differently). From 4cccf31a3eb005a2560a0479b42aa8ef2f4b5939 Mon Sep 17 00:00:00 2001 From: naveen <172697+naveensrinivasan@users.noreply.github.com> Date: Tue, 26 Apr 2022 01:07:59 +0000 Subject: [PATCH 132/159] chore: Set permissions for GitHub actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much. - Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/) Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bafe9cb8..932649f61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -309,6 +309,9 @@ jobs: webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} cleanup-prior-runs: + permissions: + actions: write # for rokroskar/workflow-run-cleanup-action to obtain workflow name & cancel it + contents: read # for rokroskar/workflow-run-cleanup-action to obtain branch runs-on: ubuntu-20.04 steps: - name: Cleanup previous runs on this branch From a35dc843ea75fe8a4c5452ab8534b0c077bfc106 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 25 Apr 2022 22:39:58 -0600 Subject: [PATCH 133/159] removed asyncio from bot_start example --- docs/strategy-callbacks.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index a53a6992c..e0cfbe8c1 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -34,17 +34,12 @@ class AwesomeStrategy(IStrategy): # ... populate_* methods - async def some_asynchronous_task(self): - self.dp['remote_data'] = requests.get('https://some_remote_source.example.com') - def bot_start(self, **kwargs) -> None: """ Called only once after bot instantiation. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. """ - self.loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.loop) - self.loop.run_until_complete(self.some_asynchronous_task()) + self.dp['remote_data'] = requests.get('https://some_remote_source.example.com') ``` ## Bot loop start From 6d99222320f05de1f7c2607f0cbe1beb8a38c29f Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Tue, 26 Apr 2022 09:39:15 +0300 Subject: [PATCH 134/159] Add 'exit_tag' parameter to 'custom_exit_price' callback. --- docs/strategy-callbacks.md | 2 +- freqtrade/freqtradebot.py | 3 ++- freqtrade/optimize/backtesting.py | 3 ++- freqtrade/strategy/interface.py | 3 ++- .../templates/subtemplates/strategy_methods_advanced.j2 | 3 ++- tests/test_freqtradebot.py | 6 +++--- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 7ec600a58..005f94155 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -376,7 +376,7 @@ class AwesomeStrategy(IStrategy): def custom_exit_price(self, pair: str, trade: Trade, current_time: datetime, proposed_rate: float, - current_profit: float, **kwargs) -> float: + current_profit: float, exit_tag: Optional[str, **kwargs) -> float: dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 57d7cac3c..68623c748 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1373,7 +1373,8 @@ class FreqtradeBot(LoggingMixin): default_retval=proposed_limit_rate)( pair=trade.pair, trade=trade, current_time=datetime.now(timezone.utc), - proposed_rate=proposed_limit_rate, current_profit=current_profit) + proposed_rate=proposed_limit_rate, current_profit=current_profit, + exit_tag=exit_check.exit_reason) limit = self.get_valid_price(custom_exit_price, proposed_limit_rate) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 27e14ba93..21e124e72 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -540,7 +540,8 @@ class Backtesting: default_retval=closerate)( pair=trade.pair, trade=trade, current_time=exit_candle_time, - proposed_rate=closerate, current_profit=current_profit) + proposed_rate=closerate, current_profit=current_profit, + exit_tag=exit_.exit_reason) # We can't place orders lower than current low. # freqtrade does not support this in live, and the order would fill immediately if trade.is_short: diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 300010b83..4f9e91b56 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -355,7 +355,7 @@ class IStrategy(ABC, HyperStrategyMixin): def custom_exit_price(self, pair: str, trade: Trade, current_time: datetime, proposed_rate: float, - current_profit: float, **kwargs) -> float: + current_profit: float, exit_tag: Optional[str], **kwargs) -> float: """ Custom exit price logic, returning the new exit price. @@ -368,6 +368,7 @@ class IStrategy(ABC, HyperStrategyMixin): :param current_time: datetime object, containing the current datetime :param proposed_rate: Rate, calculated based on pricing settings in exit_pricing. :param current_profit: Current profit (as ratio), calculated based on current_rate. + :param exit_tag: Exit reason. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return float: New exit price value if provided """ diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index d5e2ea8ce..3fa36d506 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -32,7 +32,7 @@ def custom_entry_price(self, pair: str, current_time: 'datetime', proposed_rate: def custom_exit_price(self, pair: str, trade: 'Trade', current_time: 'datetime', proposed_rate: float, - current_profit: float, **kwargs) -> float: + current_profit: float, exit_tag: Optional[str, **kwargs) -> float: """ Custom exit price logic, returning the new exit price. @@ -45,6 +45,7 @@ def custom_exit_price(self, pair: str, trade: 'Trade', :param current_time: datetime object, containing the current datetime :param proposed_rate: Rate, calculated based on pricing settings in exit_pricing. :param current_profit: Current profit (as ratio), calculated based on current_rate. + :param exit_tag: Exit reason. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return float: New exit price value if provided """ diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 3737c7c05..84d3c3324 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -3221,7 +3221,7 @@ def test_execute_trade_exit_custom_exit_price( freqtrade.execute_trade_exit( trade=trade, limit=ticker_usdt_sell_up()['ask' if is_short else 'bid'], - exit_check=ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL) + exit_check=ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL, exit_reason='foo') ) # Sell price must be different to default bid price @@ -3249,8 +3249,8 @@ def test_execute_trade_exit_custom_exit_price( 'profit_ratio': profit_ratio, 'stake_currency': 'USDT', 'fiat_currency': 'USD', - 'sell_reason': ExitType.EXIT_SIGNAL.value, - 'exit_reason': ExitType.EXIT_SIGNAL.value, + 'sell_reason': 'foo', + 'exit_reason': 'foo', 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, From 108f11b1d796dc8a371250f2dbb028161bad5739 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Apr 2022 06:42:56 +0200 Subject: [PATCH 135/159] Fix docs typos --- docs/strategy-callbacks.md | 2 +- freqtrade/templates/subtemplates/strategy_methods_advanced.j2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 005f94155..563b5a2cb 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -376,7 +376,7 @@ class AwesomeStrategy(IStrategy): def custom_exit_price(self, pair: str, trade: Trade, current_time: datetime, proposed_rate: float, - current_profit: float, exit_tag: Optional[str, **kwargs) -> float: + current_profit: float, exit_tag: Optional[str], **kwargs) -> float: dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index 3fa36d506..ed40ef509 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -32,7 +32,7 @@ def custom_entry_price(self, pair: str, current_time: 'datetime', proposed_rate: def custom_exit_price(self, pair: str, trade: 'Trade', current_time: 'datetime', proposed_rate: float, - current_profit: float, exit_tag: Optional[str, **kwargs) -> float: + current_profit: float, exit_tag: Optional[str], **kwargs) -> float: """ Custom exit price logic, returning the new exit price. From ad7fbfab1bacbfaa3778595d2f073411286f9619 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Apr 2022 13:27:33 +0200 Subject: [PATCH 136/159] Slightly improved styling --- freqtrade/rpc/telegram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index c2531fec3..1a9be4503 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -943,7 +943,7 @@ class Telegram(RPCHandler): else: fiat_currency = self._config.get('fiat_display_currency', '') try: - statlist, head, fiat_profit_sum = self._rpc._rpc_status_table( + statlist, _, _ = self._rpc._rpc_status_table( self._config['stake_currency'], fiat_currency) except RPCException: self._send_msg(msg='No open trade found.') From 30c9dc697530fda7add40cf7cae941df4cb06076 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Apr 2022 13:53:11 +0200 Subject: [PATCH 137/159] Fix exit-signa being assigned when tag is set but no signal is present. --- freqtrade/optimize/backtesting.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 21e124e72..210eab39b 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -54,6 +54,11 @@ ESHORT_IDX = 8 # Exit short ENTER_TAG_IDX = 9 EXIT_TAG_IDX = 10 +# Every change to this headers list must evaluate further usages of the resulting tuple +# and eventually change the constants for indexes at the top +HEADERS = ['date', 'open', 'high', 'low', 'close', 'enter_long', 'exit_long', + 'enter_short', 'exit_short', 'enter_tag', 'exit_tag'] + class Backtesting: """ @@ -305,10 +310,7 @@ class Backtesting: :param processed: a processed dictionary with format {pair, data}, which gets cleared to optimize memory usage! """ - # Every change to this headers list must evaluate further usages of the resulting tuple - # and eventually change the constants for indexes at the top - headers = ['date', 'open', 'high', 'low', 'close', 'enter_long', 'exit_long', - 'enter_short', 'exit_short', 'enter_tag', 'exit_tag'] + data: Dict = {} self.progress.init_step(BacktestState.CONVERT, len(processed)) @@ -320,7 +322,7 @@ class Backtesting: if not pair_data.empty: # Cleanup from prior runs - pair_data.drop(headers[5:] + ['buy', 'sell'], axis=1, errors='ignore') + pair_data.drop(HEADERS[5:] + ['buy', 'sell'], axis=1, errors='ignore') df_analyzed = self.strategy.advise_exit( self.strategy.advise_entry(pair_data, {'pair': pair}), @@ -339,7 +341,7 @@ class Backtesting: # To avoid using data from future, we use entry/exit signals shifted # from the previous candle - for col in headers[5:]: + for col in HEADERS[5:]: tag_col = col in ('enter_tag', 'exit_tag') if col in df_analyzed.columns: df_analyzed.loc[:, col] = df_analyzed.loc[:, col].replace( @@ -351,7 +353,7 @@ class Backtesting: # Convert from Pandas to list for performance reasons # (Looping Pandas is slow.) - data[pair] = df_analyzed[headers].values.tolist() if not df_analyzed.empty else [] + data[pair] = df_analyzed[HEADERS].values.tolist() if not df_analyzed.empty else [] return data def _get_close_rate(self, row: Tuple, trade: LocalTrade, exit: ExitCheckTuple, @@ -515,10 +517,10 @@ class Backtesting: exit_candle_time: datetime = row[DATE_IDX].to_pydatetime() enter = row[SHORT_IDX] if trade.is_short else row[LONG_IDX] - exit_ = row[ESHORT_IDX] if trade.is_short else row[ELONG_IDX] + exit_sig = row[ESHORT_IDX] if trade.is_short else row[ELONG_IDX] exit_ = self.strategy.should_exit( trade, row[OPEN_IDX], exit_candle_time, # type: ignore - enter=enter, exit_=exit_, + enter=enter, exit_=exit_sig, low=row[LOW_IDX], high=row[HIGH_IDX] ) @@ -568,6 +570,7 @@ class Backtesting: len(row) > EXIT_TAG_IDX and row[EXIT_TAG_IDX] is not None and len(row[EXIT_TAG_IDX]) > 0 + and exit_.exit_type in (ExitType.EXIT_SIGNAL,) ): trade.exit_reason = row[EXIT_TAG_IDX] @@ -626,9 +629,7 @@ class Backtesting: detail_data.loc[:, 'exit_short'] = row[ESHORT_IDX] detail_data.loc[:, 'enter_tag'] = row[ENTER_TAG_IDX] detail_data.loc[:, 'exit_tag'] = row[EXIT_TAG_IDX] - headers = ['date', 'open', 'high', 'low', 'close', 'enter_long', 'exit_long', - 'enter_short', 'exit_short', 'enter_tag', 'exit_tag'] - for det_row in detail_data[headers].values.tolist(): + for det_row in detail_data[HEADERS].values.tolist(): res = self._get_exit_trade_entry_for_candle(trade, det_row) if res: return res From 2c0a7c5d74df52a4ff166bc23515d318b5d08466 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Apr 2022 17:01:23 +0200 Subject: [PATCH 138/159] Don't call interest_rate and isolated_liq twice --- freqtrade/freqtradebot.py | 12 ------------ tests/test_freqtradebot.py | 12 +++++------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 68623c748..c82f2c8fe 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -664,16 +664,6 @@ class FreqtradeBot(LoggingMixin): amount = safe_value_fallback(order, 'filled', 'amount') enter_limit_filled_price = safe_value_fallback(order, 'average', 'price') - # TODO: this might be unnecessary, as we're calling it in update_trade_state. - isolated_liq = self.exchange.get_liquidation_price( - leverage=leverage, - pair=pair, - amount=amount, - open_rate=enter_limit_filled_price, - is_short=is_short - ) - interest_rate = self.exchange.get_interest_rate() - # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL fee = self.exchange.get_fee(symbol=pair, taker_or_maker='maker') base_currency = self.exchange.get_pair_base_currency(pair) @@ -702,8 +692,6 @@ class FreqtradeBot(LoggingMixin): timeframe=timeframe_to_minutes(self.config['timeframe']), leverage=leverage, is_short=is_short, - interest_rate=interest_rate, - liquidation_price=isolated_liq, trading_mode=self.trading_mode, funding_fees=funding_fees ) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 84d3c3324..89fe88a2c 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -717,12 +717,12 @@ def test_process_informative_pairs_added(default_conf_usdt, ticker_usdt, mocker) (True, 'spot', 'gateio', None, 0.0, None), (False, 'spot', 'okx', None, 0.0, None), (True, 'spot', 'okx', None, 0.0, None), - (True, 'futures', 'binance', 'isolated', 0.0, 11.89108910891089), - (False, 'futures', 'binance', 'isolated', 0.0, 8.070707070707071), + (True, 'futures', 'binance', 'isolated', 0.0, 11.88151815181518), + (False, 'futures', 'binance', 'isolated', 0.0, 8.080471380471382), (True, 'futures', 'gateio', 'isolated', 0.0, 11.87413417771621), (False, 'futures', 'gateio', 'isolated', 0.0, 8.085708510208207), - (True, 'futures', 'binance', 'isolated', 0.05, 11.796534653465345), - (False, 'futures', 'binance', 'isolated', 0.05, 8.167171717171717), + (True, 'futures', 'binance', 'isolated', 0.05, 11.7874422442244), + (False, 'futures', 'binance', 'isolated', 0.05, 8.17644781144781), (True, 'futures', 'gateio', 'isolated', 0.05, 11.7804274688304), (False, 'futures', 'gateio', 'isolated', 0.05, 8.181423084697796), (True, 'futures', 'okx', 'isolated', 0.0, 11.87413417771621), @@ -845,6 +845,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, assert trade.open_order_id is None assert trade.open_rate == 10 assert trade.stake_amount == round(order['price'] * order['filled'] / leverage, 8) + assert pytest.approx(trade.liquidation_price) == liq_price # In case of rejected or expired order and partially filled order['status'] = 'expired' @@ -932,8 +933,6 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, assert trade.open_rate_requested == 10 # In case of custom entry price not float type - freqtrade.exchange.get_maintenance_ratio_and_amt = MagicMock(return_value=(0.01, 0.01)) - freqtrade.exchange.name = exchange_name order['status'] = 'open' order['id'] = '5568' freqtrade.strategy.custom_entry_price = lambda **kwargs: "string price" @@ -946,7 +945,6 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, trade.is_short = is_short assert trade assert trade.open_rate_requested == 10 - assert trade.liquidation_price == liq_price # In case of too high stake amount From 220927289d2419046efcaf7bae1499effa537a54 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Apr 2022 19:10:04 +0200 Subject: [PATCH 139/159] Update documentation to highlight futures supported exchanges --- README.md | 8 ++++++++ docs/index.md | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/README.md b/README.md index 679dbcab0..cad39f9ac 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,14 @@ Please read the [exchange specific notes](docs/exchanges.md) to learn about even - [X] [OKX](https://okx.com/) (Former OKEX) - [ ] [potentially many others](https://github.com/ccxt/ccxt/). _(We cannot guarantee they will work)_ +### Experimentally, freqtrade also supports futures on the following exchanges + +- [X] [Binance](https://www.binance.com/) +- [X] [Gate.io](https://www.gate.io/ref/6266643) +- [X] [OKX](https://okx.com/). + +Please make sure to read the [exchange specific notes](docs/exchanges.md), as well as the [trading with leverage](docs/leverage.md) documentation before diving in. + ### Community tested Exchanges confirmed working by the community: diff --git a/docs/index.md b/docs/index.md index 2aa80c240..e0a88a381 100644 --- a/docs/index.md +++ b/docs/index.md @@ -51,6 +51,14 @@ Please read the [exchange specific notes](exchanges.md) to learn about eventual, - [X] [OKX](https://okx.com/) (Former OKEX) - [ ] [potentially many others through ccxt](https://github.com/ccxt/ccxt/). _(We cannot guarantee they will work)_ +### Experimentally, freqtrade also supports futures on the following exchanges: + +- [X] [Binance](https://www.binance.com/) +- [X] [Gate.io](https://www.gate.io/ref/6266643) +- [X] [OKX](https://okx.com/). + +Please make sure to read the [exchange specific notes](exchanges.md), as well as the [trading with leverage](leverage.md) documentation before diving in. + ### Community tested Exchanges confirmed working by the community: From 46855221aab34d0c0687474c9e8a1af08cfa9916 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Apr 2022 19:58:19 +0200 Subject: [PATCH 140/159] Fix rounding issue with contract-sized pairs for dry-run orders --- freqtrade/exchange/exchange.py | 4 +++- freqtrade/freqtradebot.py | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index d4741bd64..b12751fff 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -785,7 +785,9 @@ class Exchange: rate: float, leverage: float, params: Dict = {}, stop_loss: bool = False) -> Dict[str, Any]: order_id = f'dry_run_{side}_{datetime.now().timestamp()}' - _amount = self.amount_to_precision(pair, amount) + # Rounding here must respect to contract sizes + _amount = self._contracts_to_amount( + pair, self.amount_to_precision(pair, self._amount_to_contracts(pair, amount))) dry_order: Dict[str, Any] = { 'id': order_id, 'symbol': pair, diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index c82f2c8fe..7c20a7f60 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -585,7 +585,6 @@ class FreqtradeBot(LoggingMixin): Executes a limit buy for the given pair :param pair: pair for which we want to create a LIMIT_BUY :param stake_amount: amount of stake-currency for the pair - :param leverage: amount of leverage applied to this trade :return: True if a buy order is created, false if it fails. """ time_in_force = self.strategy.order_time_in_force['entry'] From ca49821df011c8ebb7ec8586c08daf675d210bd4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Apr 2022 06:29:14 +0200 Subject: [PATCH 141/159] Fix race condition for loop --- freqtrade/exchange/exchange.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index d4741bd64..8ecccbce0 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -9,6 +9,7 @@ import logging from copy import deepcopy from datetime import datetime, timedelta, timezone from math import ceil +from threading import Lock from typing import Any, Coroutine, Dict, List, Literal, Optional, Tuple, Union import arrow @@ -96,6 +97,9 @@ class Exchange: self._markets: Dict = {} self._trading_fees: Dict[str, Any] = {} self._leverage_tiers: Dict[str, List[Dict]] = {} + # Lock event loop. This is necessary to avoid race-conditions when using force* commands + # Due to funding fee fetching. + self._loop_lock = Lock() self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) self._config: Dict = {} @@ -1775,7 +1779,8 @@ class Exchange: async def gather_stuff(): return await asyncio.gather(*input_coro, return_exceptions=True) - results = self.loop.run_until_complete(gather_stuff()) + with self._loop_lock: + results = self.loop.run_until_complete(gather_stuff()) for res in results: if isinstance(res, Exception): @@ -2032,9 +2037,10 @@ class Exchange: if not self.exchange_has("fetchTrades"): raise OperationalException("This exchange does not support downloading Trades.") - return self.loop.run_until_complete( - self._async_get_trade_history(pair=pair, since=since, - until=until, from_id=from_id)) + with self._loop_lock: + return self.loop.run_until_complete( + self._async_get_trade_history(pair=pair, since=since, + until=until, from_id=from_id)) @retrier def _get_funding_fees_from_exchange(self, pair: str, since: Union[datetime, int]) -> float: From 1e835896415191469a369c30cf5848d96004d7e3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Apr 2022 06:59:03 +0200 Subject: [PATCH 142/159] Fix hyperopt --- freqtrade/optimize/hyperopt.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 3ae975ca7..1dafb483c 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -468,6 +468,7 @@ class Hyperopt: self.backtesting.exchange._api = None self.backtesting.exchange._api_async = None self.backtesting.exchange.loop = None # type: ignore + self.backtesting.exchange._loop_lock = None # type: ignore # self.backtesting.exchange = None # type: ignore self.backtesting.pairlists = None # type: ignore From 2ef1181e16b8d2389f51687d3be67b78b26e01f8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Apr 2022 07:33:30 +0200 Subject: [PATCH 143/159] Simplify trade __repr__ --- freqtrade/persistence/models.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/freqtrade/persistence/models.py b/freqtrade/persistence/models.py index a9c07f12c..2cacc06e2 100644 --- a/freqtrade/persistence/models.py +++ b/freqtrade/persistence/models.py @@ -429,12 +429,10 @@ class LocalTrade(): def __repr__(self): open_since = self.open_date.strftime(DATETIME_PRINT_FORMAT) if self.is_open else 'closed' - leverage = self.leverage or 1.0 - is_short = self.is_short or False return ( f'Trade(id={self.id}, pair={self.pair}, amount={self.amount:.8f}, ' - f'is_short={is_short}, leverage={leverage}, ' + f'is_short={self.is_short or False}, leverage={self.leverage or 1.0}, ' f'open_rate={self.open_rate:.8f}, open_since={open_since})' ) From 64072f76b9760679bebb24b66cd4dc52ba85d40f Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Apr 2022 14:40:47 +0200 Subject: [PATCH 144/159] Don't fail scheduled ci tasks due to notification --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bafe9cb8..0a87e2c81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -321,6 +321,8 @@ jobs: notify-complete: needs: [ build_linux, build_macos, build_windows, docs_check, mypy_version_check ] runs-on: ubuntu-20.04 + # Discord notification can't handle schedule events + if: (github.event_name != 'schedule') steps: - name: Check user permission From 4c95996069dc161fa3c6aaba8cdc6ad9629a6250 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Apr 2022 14:50:50 +0200 Subject: [PATCH 145/159] Add Permissions for notify-complete job --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 932649f61..9e7ebfc6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -324,6 +324,8 @@ jobs: notify-complete: needs: [ build_linux, build_macos, build_windows, docs_check, mypy_version_check ] runs-on: ubuntu-20.04 + permissions: + repository-projects: read steps: - name: Check user permission From cb5c3316d1e3dd63658de539c94eb559d91e4e73 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Apr 2022 19:43:52 +0200 Subject: [PATCH 146/159] Simplify log output --- freqtrade/exchange/exchange.py | 4 ++-- tests/exchange/test_exchange.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 6bb4eb446..82dcacb51 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -171,7 +171,7 @@ class Exchange: self._api_async = self._init_ccxt( exchange_config, ccxt_async, ccxt_kwargs=ccxt_async_config) - logger.info('Using Exchange "%s"', self.name) + logger.info(f'Using Exchange "{self.name}"') if validate: # Check if timeframe is available @@ -559,7 +559,7 @@ class Exchange: # Therefore we also show that. raise OperationalException( f"The ccxt library does not provide the list of timeframes " - f"for the exchange \"{self.name}\" and this exchange " + f"for the exchange {self.name} and this exchange " f"is therefore not supported. ccxt fetchOHLCV: {self.exchange_has('fetchOHLCV')}") if timeframe and (timeframe not in self.timeframes): diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index a6918b6d4..689ffa4ce 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -909,7 +909,7 @@ def test_validate_timeframes_emulated_ohlcv_1(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency') with pytest.raises(OperationalException, match=r'The ccxt library does not provide the list of timeframes ' - r'for the exchange ".*" and this exchange ' + r'for the exchange .* and this exchange ' r'is therefore not supported. *'): Exchange(default_conf) @@ -930,7 +930,7 @@ def test_validate_timeframes_emulated_ohlcvi_2(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency') with pytest.raises(OperationalException, match=r'The ccxt library does not provide the list of timeframes ' - r'for the exchange ".*" and this exchange ' + r'for the exchange .* and this exchange ' r'is therefore not supported. *'): Exchange(default_conf) From d1a61f9c615fb7e5d9717c126d9280bccf3e30ec Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Apr 2022 20:05:19 +0200 Subject: [PATCH 147/159] Don't start futures backtest if leverage-tiers don't contain pair --- freqtrade/optimize/backtesting.py | 8 ++++++++ tests/optimize/test_backtesting.py | 33 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 210eab39b..0f816f295 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -269,10 +269,18 @@ class Backtesting: candle_type=CandleType.from_string(self.exchange._ft_has["mark_ohlcv_price"]) ) # Combine data to avoid combining the data per trade. + unavailable_pairs = [] for pair in self.pairlists.whitelist: + if pair not in self.exchange._leverage_tiers: + unavailable_pairs.append(pair) + continue self.futures_data[pair] = funding_rates_dict[pair].merge( mark_rates_dict[pair], on='date', how="inner", suffixes=["_fund", "_mark"]) + 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.") else: self.futures_data = {} diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index d7ee4a042..a51e1b654 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -1341,6 +1341,39 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat assert 'STRATEGY SUMMARY' in captured.out +@pytest.mark.filterwarnings("ignore:deprecated") +def test_backtest_start_futures_noliq(default_conf_usdt, mocker, + caplog, testdatadir, capsys): + # Tests detail-data loading + default_conf_usdt.update({ + "trading_mode": "futures", + "margin_mode": "isolated", + "use_exit_signal": True, + "exit_profit_only": False, + "exit_profit_offset": 0.0, + "ignore_roi_if_entry_signal": False, + "strategy": CURRENT_TEST_STRATEGY, + }) + patch_exchange(mocker) + + mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist', + PropertyMock(return_value=['HULUMULU/USDT', 'XRP/USDT'])) + # mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', backtestmock) + + patched_configuration_load_config_file(mocker, default_conf_usdt) + + args = [ + 'backtesting', + '--config', 'config.json', + '--datadir', str(testdatadir), + '--strategy-path', str(Path(__file__).parents[1] / 'strategy/strats'), + '--timeframe', '1h', + ] + args = get_args(args) + with pytest.raises(OperationalException, match=r"Pairs .* got no leverage tiers available\."): + start_backtesting(args) + + @pytest.mark.filterwarnings("ignore:deprecated") def test_backtest_start_nomock_futures(default_conf_usdt, mocker, caplog, testdatadir, capsys): From 21df1b0db32f04bbb362c33afa483f17c328bfb7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 27 Apr 2022 13:13:11 +0200 Subject: [PATCH 148/159] Use ORJSON for http responses --- freqtrade/rpc/api_server/webserver.py | 4 ++-- requirements.txt | 2 ++ setup.py | 1 + tests/rpc/test_rpc_apiserver.py | 3 +-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/freqtrade/rpc/api_server/webserver.py b/freqtrade/rpc/api_server/webserver.py index 63812f52f..0da129583 100644 --- a/freqtrade/rpc/api_server/webserver.py +++ b/freqtrade/rpc/api_server/webserver.py @@ -2,7 +2,7 @@ import logging from ipaddress import IPv4Address from typing import Any, Dict -import rapidjson +import orjson import uvicorn from fastapi import Depends, FastAPI from fastapi.middleware.cors import CORSMiddleware @@ -24,7 +24,7 @@ class FTJSONResponse(JSONResponse): Use rapidjson for responses Handles NaN and Inf / -Inf in a javascript way by default. """ - return rapidjson.dumps(content).encode("utf-8") + return orjson.dumps(content, option=orjson.OPT_SERIALIZE_NUMPY) class ApiServer(RPCHandler): diff --git a/requirements.txt b/requirements.txt index de14b9f2c..ab8329979 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,6 +27,8 @@ py_find_1st==1.1.5 # Load ticker files 30% faster python-rapidjson==1.6 +# Properly format api responses +orjson==3.6.8 # Notify systemd sdnotify==0.3.2 diff --git a/setup.py b/setup.py index 250cafdc9..c5e418d0d 100644 --- a/setup.py +++ b/setup.py @@ -57,6 +57,7 @@ setup( 'pycoingecko', 'py_find_1st', 'python-rapidjson', + 'orjson', 'sdnotify', 'colorama', 'jinja2', diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 4910213b4..43f783a53 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -13,7 +13,6 @@ import uvicorn from fastapi import FastAPI from fastapi.exceptions import HTTPException from fastapi.testclient import TestClient -from numpy import isnan from requests.auth import _basic_auth_str from freqtrade.__init__ import __version__ @@ -985,7 +984,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short, assert_response(rc) resp_values = rc.json() assert len(resp_values) == 4 - assert isnan(resp_values[0]['profit_abs']) + assert resp_values[0]['profit_abs'] is None def test_api_version(botclient): From 48ff788e827ecb16a59d09260e03133ea13e6085 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Apr 2022 09:53:05 +0000 Subject: [PATCH 149/159] Clarify that stoploss is required closes #6740 --- docs/strategy-callbacks.md | 36 ++++++++++++++++++------------------ freqtrade/constants.py | 2 ++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 563b5a2cb..c5639d581 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -122,11 +122,11 @@ See [Dataframe access](strategy-advanced.md#dataframe-access) for more informati ## Custom stoploss -Called for open trade every throttling iteration (roughly every 5 seconds) until a trade is closed. +Called for open trade every iteration (roughly every 5 seconds) until a trade is closed. The usage of the custom stoploss method must be enabled by setting `use_custom_stoploss=True` on the strategy object. -The stoploss price can only ever move upwards - if the stoploss value returned from `custom_stoploss` would result in a lower stoploss price than was previously set, it will be ignored. The traditional `stoploss` value serves as an absolute lower level and will be instated as the initial stoploss (before this method is called for the first time for a trade). +The stoploss price can only ever move upwards - if the stoploss value returned from `custom_stoploss` would result in a lower stoploss price than was previously set, it will be ignored. The traditional `stoploss` value serves as an absolute lower level and will be instated as the initial stoploss (before this method is called for the first time for a trade), and is still mandatory. The method must return a stoploss value (float / number) as a percentage of the current price. E.g. If the `current_rate` is 200 USD, then returning `0.02` will set the stoploss price 2% lower, at 196 USD. @@ -365,13 +365,13 @@ class AwesomeStrategy(IStrategy): # ... populate_* methods - def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, + def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, entry_tag: Optional[str], side: str, **kwargs) -> float: dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) new_entryprice = dataframe['bollinger_10_lowerband'].iat[-1] - + return new_entryprice def custom_exit_price(self, pair: str, trade: Trade, @@ -381,14 +381,14 @@ class AwesomeStrategy(IStrategy): dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) new_exitprice = dataframe['bollinger_10_upperband'].iat[-1] - + return new_exitprice ``` !!! Warning - Modifying entry and exit prices will only work for limit orders. Depending on the price chosen, this can result in a lot of unfilled orders. By default the maximum allowed distance between the current price and the custom price is 2%, this value can be changed in config with the `custom_price_max_distance_ratio` parameter. - **Example**: + Modifying entry and exit prices will only work for limit orders. Depending on the price chosen, this can result in a lot of unfilled orders. By default the maximum allowed distance between the current price and the custom price is 2%, this value can be changed in config with the `custom_price_max_distance_ratio` parameter. + **Example**: If the new_entryprice is 97, the proposed_rate is 100 and the `custom_price_max_distance_ratio` is set to 2%, The retained valid custom entry price will be 98, which is 2% below the current (proposed) rate. !!! Warning "Backtesting" @@ -430,7 +430,7 @@ class AwesomeStrategy(IStrategy): 'exit': 60 * 25 } - def check_entry_timeout(self, pair: str, trade: 'Trade', order: 'Order', + def check_entry_timeout(self, pair: str, trade: 'Trade', order: 'Order', current_time: datetime, **kwargs) -> bool: if trade.open_rate > 100 and trade.open_date_utc < current_time - timedelta(minutes=5): return True @@ -508,7 +508,7 @@ class AwesomeStrategy(IStrategy): # ... populate_* methods def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, - time_in_force: str, current_time: datetime, entry_tag: Optional[str], + time_in_force: str, current_time: datetime, entry_tag: Optional[str], side: str, **kwargs) -> bool: """ Called right before placing a entry order. @@ -616,35 +616,35 @@ from freqtrade.persistence import Trade class DigDeeperStrategy(IStrategy): - + position_adjustment_enable = True - + # Attempts to handle large drops with DCA. High stoploss is required. stoploss = -0.30 - + # ... populate_* methods - + # Example specific variables max_entry_position_adjustment = 3 # This number is explained a bit further down 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, proposed_stake: float, min_stake: float, max_stake: 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 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: float, max_stake: float, **kwargs): """ Custom trade adjustment logic, returning the stake amount that a trade should be increased. This means extra buy orders with additional fees. - + :param trade: trade object. :param current_time: datetime object, containing the current datetime :param current_rate: Current buy rate. @@ -654,7 +654,7 @@ class DigDeeperStrategy(IStrategy): :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return float: Stake amount to adjust your trade """ - + if current_profit > -0.05: return None diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 1a21ec77f..3b98ce56b 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -459,6 +459,8 @@ SCHEMA_BACKTEST_REQUIRED = [ 'stake_currency', 'stake_amount', 'dry_run_wallet', + 'stoploss', + 'minimal_roi', 'dataformat_ohlcv', 'dataformat_trades', ] From b6bee45e82604a06f3143aa10967c0641847e779 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Apr 2022 09:54:54 +0000 Subject: [PATCH 150/159] Exclude user_data from isort --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 50f0242a8..e8d5ed47e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ exclude = ''' line_length = 100 multi_line_output=0 lines_after_imports=2 -skip_glob = ["**/.env*", "**/env/*", "**/.venv/*", "**/docs/*"] +skip_glob = ["**/.env*", "**/env/*", "**/.venv/*", "**/docs/*", "**/user_data/*"] [tool.pytest.ini_options] asyncio_mode = "auto" From da7a6f58f94db81d3f436dacadbdf2c7a903ee1d Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Apr 2022 17:46:33 +0200 Subject: [PATCH 151/159] Revert requiring stoploss for backtest/hyperopt --- freqtrade/constants.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 3b98ce56b..1a21ec77f 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -459,8 +459,6 @@ SCHEMA_BACKTEST_REQUIRED = [ 'stake_currency', 'stake_amount', 'dry_run_wallet', - 'stoploss', - 'minimal_roi', 'dataformat_ohlcv', 'dataformat_trades', ] From fbd142844fff0065bdac6a9e8770990faf289ab3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Apr 2022 19:37:13 +0200 Subject: [PATCH 152/159] Refactor bt-caching stuff to it's own module --- freqtrade/data/btanalysis.py | 3 +- freqtrade/misc.py | 35 +----------------------- freqtrade/optimize/backtest_caching.py | 38 ++++++++++++++++++++++++++ freqtrade/optimize/backtesting.py | 2 +- freqtrade/optimize/optimize_reports.py | 4 +-- tests/optimize/test_backtesting.py | 2 +- 6 files changed, 45 insertions(+), 39 deletions(-) create mode 100644 freqtrade/optimize/backtest_caching.py diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index 206a6f5f3..0c8e721c0 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -12,7 +12,8 @@ import pandas as pd from freqtrade.constants import LAST_BT_RESULT_FN from freqtrade.exceptions import OperationalException -from freqtrade.misc import get_backtest_metadata_filename, json_load +from freqtrade.misc import json_load +from freqtrade.optimize.backtest_caching import get_backtest_metadata_filename from freqtrade.persistence import LocalTrade, Trade, init_db diff --git a/freqtrade/misc.py b/freqtrade/misc.py index 55a533725..c3968e61c 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -2,13 +2,11 @@ Various tool function for Freqtrade and scripts """ import gzip -import hashlib import logging import re -from copy import deepcopy from datetime import datetime from pathlib import Path -from typing import Any, Iterator, List, Union +from typing import Any, Iterator, List from typing.io import IO from urllib.parse import urlparse @@ -251,34 +249,3 @@ def parse_db_uri_for_logging(uri: str): return uri pwd = parsed_db_uri.netloc.split(':')[1].split('@')[0] return parsed_db_uri.geturl().replace(f':{pwd}@', ':*****@') - - -def get_strategy_run_id(strategy) -> str: - """ - Generate unique identification hash for a backtest run. Identical config and strategy file will - always return an identical hash. - :param strategy: strategy object. - :return: hex string id. - """ - digest = hashlib.sha1() - config = deepcopy(strategy.config) - - # Options that have no impact on results of individual backtest. - not_important_keys = ('strategy_list', 'original_config', 'telegram', 'api_server') - for k in not_important_keys: - if k in config: - del config[k] - - # Explicitly allow NaN values (e.g. max_open_trades). - # as it does not matter for getting the hash. - digest.update(rapidjson.dumps(config, default=str, - number_mode=rapidjson.NM_NAN).encode('utf-8')) - with open(strategy.__file__, 'rb') as fp: - digest.update(fp.read()) - return digest.hexdigest().lower() - - -def get_backtest_metadata_filename(filename: Union[Path, str]) -> Path: - """Return metadata filename for specified backtest results file.""" - filename = Path(filename) - return filename.parent / Path(f'{filename.stem}.meta{filename.suffix}') diff --git a/freqtrade/optimize/backtest_caching.py b/freqtrade/optimize/backtest_caching.py new file mode 100644 index 000000000..c2a9903fa --- /dev/null +++ b/freqtrade/optimize/backtest_caching.py @@ -0,0 +1,38 @@ +import hashlib +from copy import deepcopy +from pathlib import Path +from typing import Union + +import rapidjson + + +def get_strategy_run_id(strategy) -> str: + """ + Generate unique identification hash for a backtest run. Identical config and strategy file will + always return an identical hash. + :param strategy: strategy object. + :return: hex string id. + """ + digest = hashlib.sha1() + config = deepcopy(strategy.config) + + # Options that have no impact on results of individual backtest. + not_important_keys = ('strategy_list', 'original_config', 'telegram', 'api_server') + for k in not_important_keys: + if k in config: + del config[k] + + # Explicitly allow NaN values (e.g. max_open_trades). + # as it does not matter for getting the hash. + digest.update(rapidjson.dumps(config, default=str, + number_mode=rapidjson.NM_NAN).encode('utf-8')) + + with open(strategy.__file__, 'rb') as fp: + digest.update(fp.read()) + return digest.hexdigest().lower() + + +def get_backtest_metadata_filename(filename: Union[Path, str]) -> Path: + """Return metadata filename for specified backtest results file.""" + filename = Path(filename) + return filename.parent / Path(f'{filename.stem}.meta{filename.suffix}') diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 0f816f295..db4496f0f 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -24,8 +24,8 @@ from freqtrade.enums import (BacktestState, CandleType, ExitCheckTuple, ExitType TradingMode) from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds -from freqtrade.misc import get_strategy_run_id from freqtrade.mixins import LoggingMixin +from freqtrade.optimize.backtest_caching import get_strategy_run_id from freqtrade.optimize.bt_progress import BTProgress from freqtrade.optimize.optimize_reports import (generate_backtest_stats, show_backtest_results, store_backtest_signal_candles, diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index dd058aff4..1d58dc339 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -11,8 +11,8 @@ from tabulate import tabulate from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT from freqtrade.data.btanalysis import (calculate_cagr, calculate_csum, calculate_market_change, calculate_max_drawdown) -from freqtrade.misc import (decimals_per_coin, file_dump_joblib, file_dump_json, - get_backtest_metadata_filename, round_coin_value) +from freqtrade.misc import decimals_per_coin, file_dump_joblib, file_dump_json, round_coin_value +from freqtrade.optimize.backtest_caching import get_backtest_metadata_filename logger = logging.getLogger(__name__) diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index a51e1b654..7494155b4 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -22,7 +22,7 @@ from freqtrade.data.history import get_timerange from freqtrade.enums import ExitType, RunMode from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exchange.exchange import timeframe_to_next_date -from freqtrade.misc import get_strategy_run_id +from freqtrade.optimize.backtest_caching import get_strategy_run_id from freqtrade.optimize.backtesting import Backtesting from freqtrade.persistence import LocalTrade from freqtrade.resolvers import StrategyResolver From 43049e04652483ff039ee7765a0181d2ed1ca337 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Apr 2022 19:44:17 +0200 Subject: [PATCH 153/159] Evict cache if parameter file changed closes #6735 --- freqtrade/optimize/backtest_caching.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtest_caching.py b/freqtrade/optimize/backtest_caching.py index c2a9903fa..d9d270072 100644 --- a/freqtrade/optimize/backtest_caching.py +++ b/freqtrade/optimize/backtest_caching.py @@ -26,7 +26,9 @@ def get_strategy_run_id(strategy) -> str: # as it does not matter for getting the hash. digest.update(rapidjson.dumps(config, default=str, number_mode=rapidjson.NM_NAN).encode('utf-8')) - + # Include _ft_params_from_file - so changing parameter files cause cache eviction + digest.update(rapidjson.dumps( + strategy._ft_params_from_file, default=str, number_mode=rapidjson.NM_NAN).encode('utf-8')) with open(strategy.__file__, 'rb') as fp: digest.update(fp.read()) return digest.hexdigest().lower() From f23faac36880027896de8d7bcc21f5af9edd6714 Mon Sep 17 00:00:00 2001 From: erdieee <58039191+erdieee@users.noreply.github.com> Date: Fri, 29 Apr 2022 20:10:50 +0200 Subject: [PATCH 154/159] Fix config_examples typo --- config_examples/config_binance.example.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_examples/config_binance.example.json b/config_examples/config_binance.example.json index ad8862afa..35b9fcd20 100644 --- a/config_examples/config_binance.example.json +++ b/config_examples/config_binance.example.json @@ -90,7 +90,7 @@ }, "bot_name": "freqtrade", "initial_state": "running", - "force_enter_enable": false, + "force_entry_enable": false, "internals": { "process_throttle_secs": 5 } From 788d9f5b55cef5657ad476d6feef8cbd227a3dec Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Fri, 29 Apr 2022 22:20:26 -0600 Subject: [PATCH 155/159] updated bot_start documentation with working example --- docs/strategy-callbacks.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index e0cfbe8c1..b01959e10 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -39,7 +39,10 @@ class AwesomeStrategy(IStrategy): Called only once after bot instantiation. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. """ - self.dp['remote_data'] = requests.get('https://some_remote_source.example.com') + if self.config['runmode'].value in ('live', 'dry_run'): + # Assign this to the class by using self.* + # can then be used by populate_* methods + self.remote_data = requests.get('https://some_remote_source.example.com') ``` ## Bot loop start From 23431a71064367496d8250ca7a7dd20b97da63d4 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Fri, 29 Apr 2022 22:21:22 -0600 Subject: [PATCH 156/159] removed invalid plotting and test_default_strategy tests for bot_start, edited edge test --- tests/optimize/test_edge_cli.py | 2 +- tests/strategy/test_default_strategy.py | 1 - tests/test_plotting.py | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/optimize/test_edge_cli.py b/tests/optimize/test_edge_cli.py index d9711b318..8241a5362 100644 --- a/tests/optimize/test_edge_cli.py +++ b/tests/optimize/test_edge_cli.py @@ -94,7 +94,7 @@ def test_edge_init(mocker, edge_conf) -> None: assert edge_cli.config == edge_conf assert edge_cli.config['stake_amount'] == 'unlimited' assert callable(edge_cli.edge.calculate) - assert edge_conf['strategy'].bot_started is True + assert edge_cli.strategy.bot_started is True def test_edge_init_fee(mocker, edge_conf) -> None: diff --git a/tests/strategy/test_default_strategy.py b/tests/strategy/test_default_strategy.py index a60274afd..5cb8fce16 100644 --- a/tests/strategy/test_default_strategy.py +++ b/tests/strategy/test_default_strategy.py @@ -32,7 +32,6 @@ def test_strategy_test_v3(result, fee, is_short, side): assert type(indicators) is DataFrame assert type(strategy.populate_buy_trend(indicators, metadata)) is DataFrame assert type(strategy.populate_sell_trend(indicators, metadata)) is DataFrame - assert strategy.bot_started is True trade = Trade( open_rate=19_000, diff --git a/tests/test_plotting.py b/tests/test_plotting.py index f0a28c4eb..97f367608 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -58,7 +58,6 @@ def test_init_plotscript(default_conf, mocker, testdatadir): assert "ohlcv" in ret assert "TRX/BTC" in ret["ohlcv"] assert "ADA/BTC" in ret["ohlcv"] - assert default_conf['strategy'].bot_started is True def test_add_indicators(default_conf, testdatadir, caplog): From 8756e7d9a1febecfae12649cc8ed21952d2f0086 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Fri, 29 Apr 2022 23:35:08 -0600 Subject: [PATCH 157/159] flake8 linting --- freqtrade/edge/edge_positioning.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/edge/edge_positioning.py b/freqtrade/edge/edge_positioning.py index 5dc84f172..fb9041574 100644 --- a/freqtrade/edge/edge_positioning.py +++ b/freqtrade/edge/edge_positioning.py @@ -90,7 +90,7 @@ class Edge: self.config['exchange']['pair_whitelist'], list(self.exchange.markets))[0]) except IndexError: self.fee = None - + strategy.bot_start() def calculate(self, pairs: List[str]) -> bool: From 09b74cebce95c80bec0f6982bf9b865523e49874 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Apr 2022 08:55:07 +0200 Subject: [PATCH 158/159] Move edge bot_loop_start to edge_cli (otherwise it's called twice when running trade mode with edge on). --- docs/strategy-callbacks.md | 6 +++--- freqtrade/edge/edge_positioning.py | 2 -- freqtrade/optimize/edge_cli.py | 1 + 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 27777c2ce..5ff499b01 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -24,11 +24,11 @@ Currently available callbacks: ## Bot start -A simple callback which is called once when the bot starts. +A simple callback which is called once when the strategy is loaded. This can be used to perform actions that must only be performed once and runs after dataprovider and wallet are set ``` python -import asyncio +import requests class AwesomeStrategy(IStrategy): @@ -42,7 +42,7 @@ class AwesomeStrategy(IStrategy): if self.config['runmode'].value in ('live', 'dry_run'): # Assign this to the class by using self.* # can then be used by populate_* methods - self.remote_data = requests.get('https://some_remote_source.example.com') + self.cust_remote_data = requests.get('https://some_remote_source.example.com') ``` ## Bot loop start diff --git a/freqtrade/edge/edge_positioning.py b/freqtrade/edge/edge_positioning.py index fb9041574..2fe41a17b 100644 --- a/freqtrade/edge/edge_positioning.py +++ b/freqtrade/edge/edge_positioning.py @@ -91,8 +91,6 @@ class Edge: except IndexError: self.fee = None - strategy.bot_start() - def calculate(self, pairs: List[str]) -> bool: if self.fee is None and pairs: self.fee = self.exchange.get_fee(pairs[0]) diff --git a/freqtrade/optimize/edge_cli.py b/freqtrade/optimize/edge_cli.py index cc9bafb0b..30eabecd0 100644 --- a/freqtrade/optimize/edge_cli.py +++ b/freqtrade/optimize/edge_cli.py @@ -44,6 +44,7 @@ class EdgeCli: self.edge._timerange = TimeRange.parse_timerange(None if self.config.get( 'timerange') is None else str(self.config.get('timerange'))) + self.strategy.bot_start() def start(self) -> None: result = self.edge.calculate(self.config['exchange']['pair_whitelist']) From 2acb68e6e24fdb6920b89fa2992d55d7f7c91bcf Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Apr 2022 13:59:23 +0200 Subject: [PATCH 159/159] Move hyperopt-loss functions to their own package --- freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_calmar.py | 0 .../optimize/{ => hyperopt_loss}/hyperopt_loss_max_drawdown.py | 0 .../optimize/{ => hyperopt_loss}/hyperopt_loss_onlyprofit.py | 0 .../{ => hyperopt_loss}/hyperopt_loss_profit_drawdown.py | 0 freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_sharpe.py | 0 .../optimize/{ => hyperopt_loss}/hyperopt_loss_sharpe_daily.py | 0 .../{ => hyperopt_loss}/hyperopt_loss_short_trade_dur.py | 0 freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_sortino.py | 0 .../optimize/{ => hyperopt_loss}/hyperopt_loss_sortino_daily.py | 0 freqtrade/resolvers/hyperopt_resolver.py | 2 +- tests/optimize/test_hyperoptloss.py | 2 +- 11 files changed, 2 insertions(+), 2 deletions(-) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_calmar.py (100%) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_max_drawdown.py (100%) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_onlyprofit.py (100%) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_profit_drawdown.py (100%) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_sharpe.py (100%) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_sharpe_daily.py (100%) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_short_trade_dur.py (100%) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_sortino.py (100%) rename freqtrade/optimize/{ => hyperopt_loss}/hyperopt_loss_sortino_daily.py (100%) diff --git a/freqtrade/optimize/hyperopt_loss_calmar.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_calmar.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py diff --git a/freqtrade/optimize/hyperopt_loss_max_drawdown.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_max_drawdown.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py diff --git a/freqtrade/optimize/hyperopt_loss_onlyprofit.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_onlyprofit.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_onlyprofit.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_onlyprofit.py diff --git a/freqtrade/optimize/hyperopt_loss_profit_drawdown.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_profit_drawdown.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_profit_drawdown.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_profit_drawdown.py diff --git a/freqtrade/optimize/hyperopt_loss_sharpe.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_sharpe.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe.py diff --git a/freqtrade/optimize/hyperopt_loss_sharpe_daily.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe_daily.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_sharpe_daily.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe_daily.py diff --git a/freqtrade/optimize/hyperopt_loss_short_trade_dur.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_short_trade_dur.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_short_trade_dur.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_short_trade_dur.py diff --git a/freqtrade/optimize/hyperopt_loss_sortino.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_sortino.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino.py diff --git a/freqtrade/optimize/hyperopt_loss_sortino_daily.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino_daily.py similarity index 100% rename from freqtrade/optimize/hyperopt_loss_sortino_daily.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino_daily.py diff --git a/freqtrade/resolvers/hyperopt_resolver.py b/freqtrade/resolvers/hyperopt_resolver.py index e3c234f60..bcfe5e1d8 100644 --- a/freqtrade/resolvers/hyperopt_resolver.py +++ b/freqtrade/resolvers/hyperopt_resolver.py @@ -23,7 +23,7 @@ class HyperOptLossResolver(IResolver): object_type = IHyperOptLoss object_type_str = "HyperoptLoss" user_subdir = USERPATH_HYPEROPTS - initial_search_path = Path(__file__).parent.parent.joinpath('optimize').resolve() + initial_search_path = Path(__file__).parent.parent.joinpath('optimize/hyperopt_loss').resolve() @staticmethod def load_hyperoptloss(config: Dict) -> IHyperOptLoss: diff --git a/tests/optimize/test_hyperoptloss.py b/tests/optimize/test_hyperoptloss.py index e3f6daf6c..4ec80ef49 100644 --- a/tests/optimize/test_hyperoptloss.py +++ b/tests/optimize/test_hyperoptloss.py @@ -4,7 +4,7 @@ from unittest.mock import MagicMock import pytest from freqtrade.exceptions import OperationalException -from freqtrade.optimize.hyperopt_loss_short_trade_dur import ShortTradeDurHyperOptLoss +from freqtrade.optimize.hyperopt_loss.hyperopt_loss_short_trade_dur import ShortTradeDurHyperOptLoss from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver